Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
(#3) Create operation execution
Browse files Browse the repository at this point in the history
  • Loading branch information
jibedoubleve committed Oct 16, 2023
1 parent caa0dec commit 8e3db5a
Show file tree
Hide file tree
Showing 23 changed files with 483 additions and 53 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,3 @@ tools

# MacOS
.DS_Store

# Jetbrain Rider
.idea
*.DotSettings.user
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// Retrieve an operation scheduler from a default location
// If the file doesn't exist, it'll create one and put default
// values (i.e. no value)
var opScheduler = OperationSchedulerFactory.FromTempFile();
var opScheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(fileName);

// Plan the actions to execute.
// Calling `Commit()` will save the operation
Expand All @@ -22,10 +22,12 @@ var opZip = OperationFactory.Unzip(zip, destination);

opScheduler.AddOperation(opDir)
.AddOperation(opZip)
.Commit();
.SavePlanAsync();

// Later, after either the machine or the application
// have been restarted, call ProcessOperations()
// to execute the operations
await opScheduler.ProcessAsync();
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(fileName);
await scheduler.ProcessAsync();
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.IO.Compression;

namespace FileOperationScheduler.Test.Helpers;

public class ZipHelper
{
/// <summary>
/// Zip the specified text file into the specified zip file
/// </summary>
/// <param name="textFile">A random text file to create in the zip</param>
/// <param name="zipFile">The resulting zip file</param>
public static void Zip(string textFile, string zipFile)
{
var sourceDir = new FileInfo(textFile).Directory?.FullName;

if (sourceDir is null) throw new FileNotFoundException($"The file '{textFile}' does not exist.");

using var fileStream = File.Create(textFile);
using var writer = new StreamWriter(fileStream);
{
writer.WriteLine("some random text");
writer.Flush();
writer.Close();
}

ZipFile.CreateFromDirectory(sourceDir, zipFile);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using FileOperationScheduler.Infrastructure.Operations;
using FluentAssertions;

namespace FileOperationScheduler.Test.SystemTests.Operations;

public class MoveDirectoryOperationShould : IDisposable
{
private const string SourceName = "RandomDirectory_src_MVDIR";
private const string DestinationName = "RandomDirectory_dst_MVDIR";

public MoveDirectoryOperationShould()
{
Source = Path.Combine(Path.GetTempPath(), SourceName);

Cleanup();
Directory.CreateDirectory(Source);

using (var fileStream = File.Create(Path.Combine(Source, "output.txt")))
using (var writer = new StreamWriter(fileStream))
{
writer.WriteLine("some random text");
}

Destination = Path.Combine(Path.GetTempPath(), DestinationName);
}

private string Source { get; }

private string Destination { get; }

[Fact]
public async Task BeProcessed()
{
// ACT
var moveDirectory = OperationFactory.MoveDirectory(Source, Destination);
await moveDirectory.ProcessAsync();

// ASSERT
Directory.Exists(Destination)
.Should().BeTrue($"'{Destination}' should be created");

Directory.EnumerateFiles(Destination)
.Count()
.Should().BeGreaterThan(0);
}

public void Dispose() => Cleanup();

private void Cleanup()
{
if (Directory.Exists(Source)) Directory.Delete(Source, true);
if (Directory.Exists(Destination)) Directory.Delete(Destination, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using FileOperationScheduler.Infrastructure.Operations;
using FluentAssertions;

namespace FileOperationScheduler.Test.SystemTests.Operations;

public class RemoveDirectoryOperationShould
{
[Fact]
public async Task BeProcessed()
{
// ARRANGE
var directory = Path.Combine(Path.GetTempPath(), "RandomDirectory");
Directory.CreateDirectory(directory);


// ACT
var rmdir = OperationFactory.RemoveDirectory(directory);
Directory.Exists(directory).Should().BeTrue();

await rmdir.ProcessAsync();

// ASSERT
Directory.Exists(directory).Should().BeFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using FileOperationScheduler.Infrastructure.Operations;
using FileOperationScheduler.Test.Helpers;
using FluentAssertions;
using Xunit.Abstractions;

namespace FileOperationScheduler.Test.SystemTests.Operations;

public class UnzipDirectoryOperationShould : IDisposable
{
private const string ArchiveFileName = "Package.zip";
private const string SourceDirectoryName = "RandomDirectory_src_ZIP";
private const string DestinationDirectoryName = "RandomDirectory_dst_ZIP";
private const string TextFileName = "random_text_file.txt";

public UnzipDirectoryOperationShould(ITestOutputHelper output)
{
Source = Path.Combine(Path.GetTempPath(), SourceDirectoryName);
Destination = Path.Combine(Path.GetTempPath(), DestinationDirectoryName);
ArchiveFile = Path.Combine(Path.GetTempPath(), Destination, ArchiveFileName);

Cleanup();

Directory.CreateDirectory(Source);
Directory.CreateDirectory(Destination);

var outfile = Path.Combine(Source, TextFileName);

output.WriteLine($"Source dir : '{Source}'");
output.WriteLine($"Destination dir: '{Destination}'");
output.WriteLine($"Archive dir : '{ArchiveFile}'");

ZipHelper.Zip(outfile, ArchiveFile);
}

[Fact]
public async Task BeProcessed()
{
// ACT
var unzipDir = OperationFactory.UnzipDirectory(ArchiveFile, Destination);
await unzipDir.ProcessAsync();

// ASSERT
var path = Path.Combine(Destination, TextFileName);
Directory.EnumerateFiles(Destination)
.Count(f => f == path)
.Should().BeGreaterThan(0);
}

private string Source { get; }
private string ArchiveFile { get; }
private string Destination { get; }

private void Cleanup()
{
if (Directory.Exists(Source)) Directory.Delete(Source, true);
if (Directory.Exists(Destination)) Directory.Delete(Destination, true);
if (File.Exists(ArchiveFile)) File.Delete(ArchiveFile);
}

public void Dispose() => Cleanup();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ public class SchedulerShould : IDisposable
private const string FilePattern = "lanceur_operation_log_{0}.json";
private readonly string _fileName = string.Format(FilePattern, Guid.NewGuid());

private static List<IOperation> GetRandomOperations(int count)
private static List<IOperationConfiguration> GetRandomOperations(int count)
{
var results = new List<IOperation>();
var results = new List<IOperationConfiguration>();
for (var i = 0; i < count; i++)
results.Add(
new Operation() { Name = $"NoOperation_{i}", Parameters = StringHelper.Random }
new OperationConfiguration() { Name = $"NoOperation_{i}", Parameters = new() { { "1", "un" } } }
);
return results;
}
Expand All @@ -27,7 +27,7 @@ private static List<IOperation> GetRandomOperations(int count)
public async Task CreateInMemoryBeforeSaving()
{
// ARRANGE
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var operations = GetRandomOperations(4);

var i = 0;
Expand All @@ -49,7 +49,7 @@ public async Task CreateInMemoryBeforeSaving()
public async Task RetrievePreviouslySavedScheduler()
{
// ARRANGE
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var operations = GetRandomOperations(4);

var i = 0;
Expand All @@ -73,7 +73,7 @@ await scheduler.ResetPlan()
public async Task RetrievePreviouslyAndAppendOperation()
{
// ARRANGE
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_fileName);
var operations = GetRandomOperations(4);

var i = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using FileOperationScheduler.Infrastructure;
using FileOperationScheduler.Infrastructure.Operations;
using FileOperationScheduler.Test.Helpers;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit.Abstractions;
using Newtonsoft;

namespace FileOperationScheduler.Test.SystemTests;

public class SerialiserShould : IDisposable
{
private readonly string _destinationDir = Path.Combine(Path.GetTempPath(), "destination");
private readonly string _directory = Path.Combine(Path.GetTempPath(), "toRemove");

private readonly string _jsonFile = Path.Combine(Path.GetTempPath(), $"{Path.GetRandomFileName()}.json");
private readonly string _zipFile = Path.Combine(Path.GetTempPath(), $"{Path.GetRandomFileName()}.zip");

private readonly ITestOutputHelper _output;

public SerialiserShould(ITestOutputHelper output)
{
_output = output;

_output.WriteLine($"Zip file : {_zipFile}");
_output.WriteLine($"Destination dir: {_destinationDir}");
_output.WriteLine($"Directory : {_directory}");
}


[Fact]
public async Task Serialize()
{
// ARRANGE
if (!Directory.Exists(_destinationDir)) Directory.CreateDirectory(_destinationDir);
if (!Directory.Exists(_directory)) Directory.CreateDirectory(_directory);

var textFile = Path.Combine(_directory, "some.txt");
await File.WriteAllTextAsync(textFile, "Some random text");
ZipHelper.Zip(textFile, _zipFile);
File.Delete(textFile);

var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_jsonFile);
await scheduler.AddOperation(OperationFactory.RemoveDirectory(_directory))
.AddOperation(OperationFactory.UnzipDirectory(_zipFile, _destinationDir))
.SavePlanAsync();

OutputJsonFile();

// ACT
var sut = await OperationSchedulerFactory.RetrieveFromFileAsync(_jsonFile);
await sut.ExecutePlanAsync();

// ASSERT
Directory.Exists(_directory)
.Should().BeFalse();

File.Exists(_jsonFile)
.Should().BeTrue($"'{_jsonFile}' should exist");

Directory.GetFiles(_destinationDir)
.Length
.Should().BeGreaterThan(0);
}

[Fact]
public async Task Deserialize()
{
var scheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_jsonFile);

Directory.CreateDirectory(_destinationDir);

await scheduler.AddOperation(OperationFactory.RemoveDirectory(_destinationDir))
.AddOperation(OperationFactory.UnzipDirectory(_zipFile, _destinationDir))
.SavePlanAsync();

var deserializedScheduler = await OperationSchedulerFactory.RetrieveFromFileAsync(_jsonFile);
deserializedScheduler.GetState()
.OperationCount
.Should().Be(2);
}

private void OutputJsonFile()
{
if (!File.Exists(_jsonFile))
{
_output.WriteLine($"File '{_jsonFile}' does not exist.");
return;
}

var json = File.ReadAllText(_jsonFile);
json = JsonConvert.SerializeObject(JsonConvert.DeserializeObject(json), Formatting.Indented);
_output.WriteLine("Json configuration file contains:");
_output.WriteLine(json);
}

public void Dispose()
{
if (File.Exists(_jsonFile)) File.Delete(_jsonFile);
if (File.Exists(_zipFile)) File.Delete(_zipFile);

if (Directory.Exists(_destinationDir)) Directory.Delete(_destinationDir, true);
if (Directory.Exists(_directory)) Directory.Delete(_directory, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public class SchedulerShould
public async Task CreateOperation_WhenSaved()
{
// ARRANGE
var operation1 = new Mock<IOperation>();
var operation2 = new Mock<IOperation>();
var operation3 = new Mock<IOperation>();
var operation1 = new Mock<IOperationConfiguration>();
var operation2 = new Mock<IOperationConfiguration>();
var operation3 = new Mock<IOperationConfiguration>();

// ACT
var scheduler = OperationSchedulerFactory.RetrieveFromMemory();
Expand Down
12 changes: 0 additions & 12 deletions src/FileOperationScheduler.sln.DotSettings.user

This file was deleted.

5 changes: 2 additions & 3 deletions src/FileOperationScheduler/Core/IOperation.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace FileOperationScheduler.Core;

public interface IOperation
public interface IOperation : IOperationConfiguration
{
string? Name { get; set; }
string? Parameters { get; set; }
Task ProcessAsync();
}
Loading

0 comments on commit 8e3db5a

Please sign in to comment.