using System; using System.Collections.Generic; using UnitTestSharp; namespace Glass.UnitTests { public class FileEntryOrderTests : TestFixture { private static FileEntry File(string name, long? size = null, DateTime? modified = null) { return new FileEntry(name, IsDirectory: false, size, modified); } private static FileEntry Directory(string name) { return new FileEntry(name, IsDirectory: true); } private static string[] NamesInOrder( FileEntry[] entries, FileColumn column, bool descending, FileEntryOrder order = null) { int[] permutation = (order ?? new FileEntryOrder()).Compute(entries, column, descending); var returnMe = new string[permutation.Length]; for (int i = 0; i < permutation.Length; ++i) { returnMe[i] = entries[permutation[i]].Name; } return returnMe; } public class ComputeTests : TestFixture { public void NullEntries_Throws() { CheckThrow(typeof(ArgumentNullException)); new FileEntryOrder().Compute(null, FileColumn.Name, descending: false); } public void NotAColumn_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new FileEntryOrder().Compute(new FileEntry[0], (FileColumn)5, descending: false); } public void NoEntries_GivesAnEmptyOrder() { CheckEqual(0, new FileEntryOrder().Compute(new FileEntry[0], FileColumn.Size, descending: true).Length); } public void Always_LeavesTheEntriesAlone() { FileEntry[] entries = { File("b", 2), File("a", 1) }; NamesInOrder(entries, FileColumn.Size, descending: false); CheckEqual("b", entries[0].Name); CheckEqual("a", entries[1].Name); } public void Always_GivesAPermutationOfThePositions() { FileEntry[] entries = { File("b", 2), Directory("d"), File("a", 1) }; int[] order = new FileEntryOrder().Compute(entries, FileColumn.Size, descending: true); CheckEqual(new[] { 0, 1, 2 }, SortedCopy(order)); } private static int[] SortedCopy(int[] values) { var returnMe = (int[])values.Clone(); Array.Sort(returnMe); return returnMe; } } public class ByNameTests : TestFixture { public void Ascending_IgnoresCase() { FileEntry[] entries = { File("b"), File("A"), File("c") }; CheckEqual(new[] { "A", "b", "c" }, NamesInOrder(entries, FileColumn.Name, descending: false)); } public void Ascending_PutsUpperCaseBeforeLowerCaseOfTheSameLetter() { FileEntry[] entries = { File("a"), File("A") }; CheckEqual(new[] { "A", "a" }, NamesInOrder(entries, FileColumn.Name, descending: false)); } public void Descending_ReversesTheNames() { FileEntry[] entries = { File("b"), File("A"), File("c") }; CheckEqual(new[] { "c", "b", "A" }, NamesInOrder(entries, FileColumn.Name, descending: true)); } public void Ascending_PutsDirectoriesFirst() { FileEntry[] entries = { File("a"), Directory("z"), File("b"), Directory("y") }; CheckEqual(new[] { "y", "z", "a", "b" }, NamesInOrder(entries, FileColumn.Name, descending: false)); } public void Descending_StillPutsDirectoriesFirst() { FileEntry[] entries = { File("a"), Directory("z"), File("b"), Directory("y") }; CheckEqual(new[] { "z", "y", "b", "a" }, NamesInOrder(entries, FileColumn.Name, descending: true)); } } public class BySizeTests : TestFixture { public void Ascending_PutsTheSmallestFirst() { FileEntry[] entries = { File("a", 30), File("b", 10), File("c", 20) }; CheckEqual(new[] { "b", "c", "a" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Descending_PutsTheLargestFirst() { FileEntry[] entries = { File("a", 30), File("b", 10), File("c", 20) }; CheckEqual(new[] { "a", "c", "b" }, NamesInOrder(entries, FileColumn.Size, descending: true)); } public void Ascending_PutsTiesInNameOrder() { FileEntry[] entries = { File("c", 5), File("a", 5), File("b", 5) }; CheckEqual(new[] { "a", "b", "c" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Descending_StillPutsTiesInNameOrder() { FileEntry[] entries = { File("c", 5), File("a", 5), File("b", 5), File("d", 9) }; CheckEqual(new[] { "d", "a", "b", "c" }, NamesInOrder(entries, FileColumn.Size, descending: true)); } public void Ascending_PutsAMissingSizeBeforeEmptyFiles() { FileEntry[] entries = { File("a", 0), File("b") }; CheckEqual(new[] { "b", "a" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Descending_PutsAMissingSizeLast() { FileEntry[] entries = { File("b"), File("a", 0) }; CheckEqual(new[] { "a", "b" }, NamesInOrder(entries, FileColumn.Size, descending: true)); } public void Ascending_PutsDirectoriesFirstInNameOrder() { FileEntry[] entries = { File("a", 1), Directory("z"), Directory("y") }; CheckEqual(new[] { "y", "z", "a" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Descending_StillPutsDirectoriesFirstInNameOrder() { FileEntry[] entries = { File("a", 1), Directory("z"), Directory("y") }; CheckEqual(new[] { "y", "z", "a" }, NamesInOrder(entries, FileColumn.Size, descending: true)); } public void Ascending_OrdersSizesPastFourGigabytes() { FileEntry[] entries = { File("c", 5000000000), File("a", 1000), File("d", 4294967296), File("b", 4294967295), }; CheckEqual(new[] { "a", "b", "d", "c" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Descending_OrdersSizesPastFourGigabytes() { FileEntry[] entries = { File("c", 5000000000), File("a", 1000), File("d", 4294967296), File("b", 4294967295), }; CheckEqual(new[] { "c", "d", "b", "a" }, NamesInOrder(entries, FileColumn.Size, descending: true)); } public void Ascending_OrdersSizesThatDifferOnlyInTheLowerHalf() { FileEntry[] entries = { File("a", 4294967301), File("b", 4294967299), File("c", 4294967300) }; CheckEqual(new[] { "b", "c", "a" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } public void Ascending_OrdersALowerHalfWithItsTopBitSetAfterOneWithout() { FileEntry[] entries = { File("a", 3000000000), File("b", 2000000000) }; CheckEqual(new[] { "b", "a" }, NamesInOrder(entries, FileColumn.Size, descending: false)); } } public class ByModifiedTests : TestFixture { private static readonly DateTime Early = new DateTime(2020, 1, 1); private static readonly DateTime Middle = new DateTime(2020, 6, 1); private static readonly DateTime Late = new DateTime(2021, 1, 1); public void Ascending_PutsTheOldestFirst() { FileEntry[] entries = { File("a", modified: Late), File("b", modified: Early), File("c", modified: Middle), }; CheckEqual(new[] { "b", "c", "a" }, NamesInOrder(entries, FileColumn.Modified, descending: false)); } public void Descending_PutsTheNewestFirst() { FileEntry[] entries = { File("a", modified: Late), File("b", modified: Early), File("c", modified: Middle), }; CheckEqual(new[] { "a", "c", "b" }, NamesInOrder(entries, FileColumn.Modified, descending: true)); } public void Ascending_PutsAMissingDateFirst() { FileEntry[] entries = { File("a", modified: Early), File("b") }; CheckEqual(new[] { "b", "a" }, NamesInOrder(entries, FileColumn.Modified, descending: false)); } public void Ascending_PutsTiesInNameOrder() { FileEntry[] entries = { File("b", modified: Early), File("a", modified: Early) }; CheckEqual(new[] { "a", "b" }, NamesInOrder(entries, FileColumn.Modified, descending: false)); } public void Descending_StillPutsDirectoriesFirst() { FileEntry[] entries = { File("a", modified: Late), Directory("d") }; CheckEqual(new[] { "d", "a" }, NamesInOrder(entries, FileColumn.Modified, descending: true)); } } public class ReuseTests : TestFixture { public void ASecondCallWithFewerEntries_IsNotAffectedByTheFirst() { var order = new FileEntryOrder(); FileEntry[] many = { File("a", 3), File("b", 2), File("c", 1), File("d", 0) }; FileEntry[] few = { File("y", 2), File("x", 1) }; NamesInOrder(many, FileColumn.Size, descending: false, order); CheckEqual(new[] { "x", "y" }, NamesInOrder(few, FileColumn.Size, descending: false, order)); } public void ASecondCallWithMoreEntries_GrowsToFitThem() { var order = new FileEntryOrder(); FileEntry[] few = { File("y", 2), File("x", 1) }; FileEntry[] many = { File("a", 3), File("b", 2), File("c", 1), File("d", 0) }; NamesInOrder(few, FileColumn.Size, descending: false, order); CheckEqual(new[] { "d", "c", "b", "a" }, NamesInOrder(many, FileColumn.Size, descending: false, order)); } public void EachResult_IsItsOwnArray() { var order = new FileEntryOrder(); FileEntry[] entries = { File("b", 2), File("a", 1) }; int[] first = order.Compute(entries, FileColumn.Size, descending: false); int[] second = order.Compute(entries, FileColumn.Size, descending: true); CheckEqual(new[] { 1, 0 }, first); CheckEqual(new[] { 0, 1 }, second); } } } }