From e9c86fd718857021db0b41b1648794adeb5225e6 Mon Sep 17 00:00:00 2001 From: Ogoun Date: Tue, 9 Apr 2019 18:34:17 +0300 Subject: [PATCH] Add unit tests --- ZeroLevel.UnitTests/CollectionsTests.cs | 68 +++++++- ZeroLevel.UnitTests/EncryptionTests.cs | 82 +++++++++ .../Models/CompositeInstanceFactory.cs | 155 ++++++++++++++++++ ZeroLevel.UnitTests/SerializationTests.cs | 150 +---------------- .../ZeroLevel.UnitTests.csproj | 2 + .../Services/Collections/EverythingStorage.cs | 68 +++++++- .../Collections/IEverythingStorage.cs | 20 ++- 7 files changed, 389 insertions(+), 156 deletions(-) create mode 100644 ZeroLevel.UnitTests/EncryptionTests.cs create mode 100644 ZeroLevel.UnitTests/Models/CompositeInstanceFactory.cs diff --git a/ZeroLevel.UnitTests/CollectionsTests.cs b/ZeroLevel.UnitTests/CollectionsTests.cs index 5af0b42..16e68fa 100644 --- a/ZeroLevel.UnitTests/CollectionsTests.cs +++ b/ZeroLevel.UnitTests/CollectionsTests.cs @@ -1,8 +1,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; using System.Linq; using ZeroLevel.Services.Collections; +using ZeroLevel.Services.ObjectMapping; +using ZeroLevel.Services.Reflection; -namespace ZeroLevel.UnitTests +namespace ZeroLevel.CollectionUnitTests { [TestClass] public class CollectionsTests @@ -58,5 +61,68 @@ namespace ZeroLevel.UnitTests Assert.IsTrue(CollectionComparsionExtensions.OrderingEquals(collection.GenerateSeq().ToArray(), iter2)); Assert.IsTrue(CollectionComparsionExtensions.OrderingEquals(collection.GenerateSeq().ToArray(), iter3)); } + + [TestMethod] + public void EverythingStorageTest() + { + // Arrange + var storage = EverythingStorage.Create(); + var date = DateTime.Now; + var typeBuilder = new DTOTypeBuilder("MyType"); + typeBuilder.AppendField("Title"); + typeBuilder.AppendProperty("Id"); + typeBuilder.AppendProperty("Created"); + var type = typeBuilder.Complete(); + var mapper = TypeMapper.Create(type); + var instance = TypeHelpers.CreateNonInitializedInstance(type); + mapper.Set(instance, "Title", "This is title"); + mapper.Set(instance, "Id", 1001001); + mapper.Set(instance, "Created", date); + + // Act + storage.Add("id", "stringidentity"); + storage.Add("id", 123); + storage.Add("id", 234); + storage.Add(type, "rt", instance); + + // Assert + Assert.IsTrue(storage.ContainsKey("id")); + Assert.IsTrue(storage.ContainsKey("id")); + Assert.IsTrue(storage.ContainsKey("id")); + Assert.IsTrue(storage.ContainsKey(type, "rt")); + Assert.IsFalse(storage.ContainsKey("somekey")); + Assert.IsFalse(storage.ContainsKey("somekey")); + + Assert.AreEqual(mapper.Get(storage.Get(type, "rt"), "Id"), (long)1001001); + Assert.AreEqual(mapper.Get(storage.Get(type, "rt"), "Created"), date); + Assert.AreEqual(mapper.Get(storage.Get(type, "rt"), "Title"), "This is title"); + Assert.AreEqual(storage.Get("id"), (long)123); + Assert.AreEqual(storage.Get("id"), 234); + Assert.AreEqual(storage.Get("id"), "stringidentity"); + } + + [TestMethod] + public void FixSizeQueueTest() + { + // Arrange + var fix = new FixSizeQueue(3); + + // Act + fix.Push(1); + fix.Push(2); + fix.Push(3); + fix.Push(4); + fix.Push(5); + + // Assert + Assert.IsTrue(fix.Count == 3); + Assert.IsTrue(fix.Contains(3)); + Assert.IsTrue(fix.Contains(4)); + Assert.IsTrue(fix.Contains(5)); + Assert.IsTrue(CollectionComparsionExtensions.OrderingEquals(fix.Dump().ToArray(), new long[] { 3, 4, 5 })); + Assert.IsTrue(fix.Take() == 3); + Assert.IsTrue(fix.Count == 2); + Assert.IsTrue(CollectionComparsionExtensions.OrderingEquals(fix.Dump().ToArray(), new long[] { 4, 5 })); + } } } diff --git a/ZeroLevel.UnitTests/EncryptionTests.cs b/ZeroLevel.UnitTests/EncryptionTests.cs new file mode 100644 index 0000000..3021c39 --- /dev/null +++ b/ZeroLevel.UnitTests/EncryptionTests.cs @@ -0,0 +1,82 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Linq; +using ZeroLevel.DocumentObjectModel; +using ZeroLevel.Network; +using ZeroLevel.Services.Encryption; +using ZeroLevel.Services.Serialization; +using ZeroLevel.UnitTests.Models; + +namespace ZeroLevel.EncryptionUnitTests +{ + [TestClass] + public class EncryptionTests + { + private static double CalculateDeviation(byte[] data) + { + double average = data.Average(b => (double)b); + double sumOfSquaresOfDifferences = (double)data.Select(val => (val - average) * (val - average)).Sum(); + return Math.Sqrt(sumOfSquaresOfDifferences / data.Length); + } + + [TestMethod] + public void FastObfuscatorTest() + { + // Arrange + var comparator = new Func((left, right) => + { + var l_bin = MessageSerializer.Serialize(left); + var r_bin = MessageSerializer.Serialize(right); + return ArrayExtensions.UnsafeEquals(l_bin, r_bin); + }); + var instance = CompositeInstanceFactory.MakeDocument(); + var data = MessageSerializer.Serialize(instance); + + // Act + var obfscator = new FastObfuscator("mypassword"); + var deviation = CalculateDeviation(data); + obfscator.HashData(data); + var obf_deviation = CalculateDeviation(data); + + new FastObfuscator("mypassword").DeHashData(data); + var deobf_deviation = CalculateDeviation(data); + var clone = MessageSerializer.Deserialize(data); + + // Assert + Assert.AreEqual(deviation, deobf_deviation); + Assert.AreNotEqual(deviation, obf_deviation); + Assert.IsTrue(obf_deviation >= deviation); + Assert.IsTrue(comparator(instance, clone)); + } + + [TestMethod] + public void NetworkStreamDataObfuscatorTest() + { + // Arrange + var comparator = new Func((left, right) => + { + var l_bin = MessageSerializer.Serialize(left); + var r_bin = MessageSerializer.Serialize(right); + return ArrayExtensions.UnsafeEquals(l_bin, r_bin); + }); + var instance = CompositeInstanceFactory.MakeDocument(); + var data = MessageSerializer.Serialize(instance); + byte initial = 66; + + // Act + var deviation = CalculateDeviation(data); + NetworkStreamFastObfuscator.HashData(data, initial); + var obf_deviation = CalculateDeviation(data); + + NetworkStreamFastObfuscator.DeHashData(data, initial); + var deobf_deviation = CalculateDeviation(data); + var clone = MessageSerializer.Deserialize(data); + + // Assert + Assert.AreEqual(deviation, deobf_deviation); + Assert.AreNotEqual(deviation, obf_deviation); + Assert.IsTrue(obf_deviation >= deviation); + Assert.IsTrue(comparator(instance, clone)); + } + } +} diff --git a/ZeroLevel.UnitTests/Models/CompositeInstanceFactory.cs b/ZeroLevel.UnitTests/Models/CompositeInstanceFactory.cs new file mode 100644 index 0000000..8e662b2 --- /dev/null +++ b/ZeroLevel.UnitTests/Models/CompositeInstanceFactory.cs @@ -0,0 +1,155 @@ +using DOM.Services; +using System; +using ZeroLevel.DocumentObjectModel; +using ZeroLevel.Services.Serialization; + +namespace ZeroLevel.UnitTests.Models +{ + public static class CompositeInstanceFactory + { + public static Document MakeDocument() + { + var doc = new Document(); + doc.Categories.Add(new Category + { + Title = "Algorithms", + Code = "0", + DirectionCode = "Posts" + }); + doc.Categories.Add(new Category + { + Title = "Data compression", + Code = "133", + DirectionCode = "Posts" + }); + doc.Header = "Парадоксы о сжатии данных"; + doc.Summary = "Задача сжатия данных в своей простейшей форме может относиться к числам и их обозначениям. Числа можно обозначать числительными («одиннадцать» для числа 11), математическими выражениями («два в двадцатой» для 1048576), строковыми выражениями («пять девяток» для 99999), именами собственными («число зверя» для 666, «год смерти Тьюринга» для 1954), или произвольными их комбинациями. Годится любое обозначение, по которому собеседник сможет однозначно определить, о каком числе речь. Очевидно, что сообщить собеседнику «факториал восьми» эффективнее, чем эквивалентное обозначение «сорок тысяч триста двадцать». Здесь возникает логичный вопрос: какое обозначение для заданного числа самое короткое?"; + doc.DescriptiveMetadata.Byline = "tyomitch"; + doc.DescriptiveMetadata.Source.Title = "HABR"; + + doc.TagMetadata.Keywords.Add("парадокс берри"); + doc.TagMetadata.Keywords.Add("колмогоровская сложность"); + doc.TagMetadata.Keywords.Add("проблема останова"); + + doc.Identifier.Link = "https://habr.com/en/post/446976/"; + + var builder = new ContentBuilder(doc); + builder.EnterParagraph(); + builder.WriteText("Философ Бертран Рассел в 1908 опубликовал"); + builder.WriteLink("https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%B4%D0%BE%D0%BA%D1%81_%D0%91%D0%B5%D1%80%D1%80%D0%B8", "«парадокс Берри»"); + builder.WriteText(", который затрагивает вопрос обозначений чисел с противоположной стороны: какое самое маленькое число, для обозначения которого недостаточно восьмидесяти букв? Такое число обязано существовать: из восьмидесяти русских букв и пробелов можно составить всего 3480 обозначений, значит, с использованием восьмидесяти букв можно обозначить не более 3480 чисел.Значит, некое число, не большее чем 3480, обозначить таким образом невозможно."); + builder.EnterParagraph(); + builder.WriteText("Значит, этому числу будет соответствовать обозначение «самое маленькое число, для обозначения которого недостаточно восьмидесяти букв», в котором всего 78 букв! С одной стороны, это число обязано существовать; с другой, если это число существует, то его обозначение ему не соответствует. Парадокс!"); + builder.EnterParagraph(); + builder.WriteText("Самый простой способ отмахнуться от этого парадокса — сослаться на неформальность словесных обозначений. Мол, если бы в обозначениях допускался лишь конкретно определённый набор выражений, то «самое маленькое число, для обозначения которого недостаточно восьмидесяти букв» не было бы допустимым обозначением, тогда как практически полезные обозначения типа «факториал восьми» остались бы допустимыми."); + builder.EnterParagraph(); + builder.WriteText("Есть ли формальные способы описания последовательности (алгоритма) действий над числами? Есть, и в изобилии — их называют языками программирования. Будем вместо словесных обозначений использовать программы (например, на Python), выводящие нужные числа. Например, для пяти девяток подойдёт программа print(\"9\"*5). По-прежнему будем интересоваться самой короткой программой для заданного числа. Длину такой программы называют колмогоровской сложностью числа; это теоретический предел, до которого заданное число можно сжать."); + builder.EnterParagraph(); + builder.WriteText("Вместо парадокса Берри теперь можно рассмотреть аналогичный: какое самое маленькое число, для вывода которого недостаточно килобайтной программы?"); + builder.EnterParagraph(); + builder.WriteText("Рассуждать будем так же, как и раньше: существует 2561024 килобайтных текстов, значит, килобайтными программами можно вывести не более 2561024 чисел. Значит, некое число, не большее чем 2561024, вывести таким способом невозможно."); + builder.EnterParagraph(); + builder.WriteText("Но напишем на Python программу, которая генерирует все возможные килобайтные тексты, запускает их на выполнение, и если они выводят какое-то число — то добавляет это число в словарь достижимых. После проверки всех 2561024 возможностей, сколько бы времени это ни заняло — программа ищет, какое самое маленькое число отсутствует в словаре, и выводит это число. Кажется очевидным, что такая программа уложится в килобайт кода — и выведет то самое число, которое невозможно вывести килобайтной программой!"); + builder.EnterParagraph(); + builder.WriteText("В чём же подвох теперь? На неформальность обозначений его списать уже нельзя!"); + builder.EnterParagraph(); + builder.WriteText("Если вас смущает то, что наша программа потребует астрономического количества памяти для работы — словарь (или битовый массив) из 2561024 элементов — то можно всё то же самое осуществить и без него: для каждого из 2561024 чисел по очереди перебирать все 2561024 возможных программ, пока не найдётся подходящая. Не важно, что такой перебор продлится очень долго: после проверки менее чем (2561024)2 пар из числа и программы он ведь завершится, и найдёт то самое заветное число."); + builder.EnterParagraph(); + builder.WriteText("Или не завершится? Ведь среди всех программ, которые будут испробованы, встретится while True: pass (и её функциональные аналоги) — и дальше проверки такой программы дело уже не пойдёт!"); + builder.EnterParagraph(); + builder.WriteText("В отличие от парадокса Берри, где подвох был в неформальности обозначений, во втором случае мы имеем хорошо замаскированную переформулировку «проблемы остановки». Дело в том, что по программе невозможно за конечное время определить её вывод.В частности, колмогоровская сложность невычислима: нет никакого алгоритма, который бы позволил для заданного числа найти длину самой короткой программы, выводящей это число; а значит, нет решения и для задачи Берри — найти для заданного числа длину самого короткого словесного обозначения."); + builder.Complete(); + + var c1 = new Comment + { + Id = 0, + RefToId = -1, + Author = "exception13x", + Text = "С каких пор пробелы и запятые стали буквами? Если использовать «символов», то парадокс пропадает.", + Votes = 0, + DateTime = DateTime.Parse("2019-04-09 10:33") + }; + var c2 = new Comment + { + Id = 1, + RefToId = 0, + Author = "tyomitch", + Text = "Почему пропадает?", + Votes = 1, + DateTime = DateTime.Parse("2019-04-09 10:57") + }; + var c3 = new Comment + { + Id = 2, + RefToId = 1, + Author = "exception13x", + Text = "Потому что в фразе «самое маленькое число, для обозначения которого недостаточно восьмидесяти символов» будет 83 символа. Прошу прощения за придирки, меня просто зацепила фраза про 78 букв(которых 69 в исходной фразе)", + Votes = -1, + DateTime = DateTime.Parse("2019-04-09 12:12") + }; + var c4 = new Comment + { + Id = 3, + RefToId = 2, + Author = "kahi4", + Text = "ну поменять 80 на 100 и делов то, \"самое маленькое число, для обозначения которого недостаточно ста символов\".", + Votes = -1, + DateTime = DateTime.Parse("2019-04-09 12:50") + }; + doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c1)); + doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c2)); + doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c3)); + doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c4)); + return doc; + } + + private class Comment : + IBinarySerializable, IEquatable + { + public long Id; + public long RefToId; + + public DateTime DateTime; + public string Author; + + public string Text; + public int Votes; + + public void Deserialize(IBinaryReader reader) + { + this.Id = reader.ReadLong(); + this.RefToId = reader.ReadLong(); + this.DateTime = reader.ReadDateTime().Value; + this.Author = reader.ReadString(); + this.Text = reader.ReadString(); + this.Votes = reader.ReadInt32(); + } + + public override bool Equals(object obj) + { + return this.Equals(obj as Comment); + } + + public override int GetHashCode() + { + return this.Id.GetHashCode(); + } + + public bool Equals(Comment other) + { + if (other == null) return false; + return this.Id == other.Id && this.RefToId == other.RefToId && this.Votes == other.Votes; + } + + public void Serialize(IBinaryWriter writer) + { + writer.WriteLong(this.Id); + writer.WriteLong(this.RefToId); + writer.WriteDateTime(this.DateTime); + writer.WriteString(this.Author); + writer.WriteString(this.Text); + writer.WriteInt32(this.Votes); + } + } + } +} diff --git a/ZeroLevel.UnitTests/SerializationTests.cs b/ZeroLevel.UnitTests/SerializationTests.cs index 357085b..caa4fd1 100644 --- a/ZeroLevel.UnitTests/SerializationTests.cs +++ b/ZeroLevel.UnitTests/SerializationTests.cs @@ -7,6 +7,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using ZeroLevel.DocumentObjectModel; using ZeroLevel.Network; using ZeroLevel.Services.Serialization; +using ZeroLevel.UnitTests.Models; namespace ZeroLevel.UnitTests { @@ -344,152 +345,7 @@ namespace ZeroLevel.UnitTests return ArrayExtensions.UnsafeEquals(l_bin, r_bin); }); - MakePrimitiveTest(MakeDocument(), comparator); - } - - private static Document MakeDocument() - { - var doc = new Document(); - doc.Categories.Add(new Category - { - Title = "Algorithms", - Code = "0", - DirectionCode = "Posts" - }); - doc.Categories.Add(new Category - { - Title = "Data compression", - Code = "133", - DirectionCode = "Posts" - }); - doc.Header = "Парадоксы о сжатии данных"; - doc.Summary = "Задача сжатия данных в своей простейшей форме может относиться к числам и их обозначениям. Числа можно обозначать числительными («одиннадцать» для числа 11), математическими выражениями («два в двадцатой» для 1048576), строковыми выражениями («пять девяток» для 99999), именами собственными («число зверя» для 666, «год смерти Тьюринга» для 1954), или произвольными их комбинациями. Годится любое обозначение, по которому собеседник сможет однозначно определить, о каком числе речь. Очевидно, что сообщить собеседнику «факториал восьми» эффективнее, чем эквивалентное обозначение «сорок тысяч триста двадцать». Здесь возникает логичный вопрос: какое обозначение для заданного числа самое короткое?"; - doc.DescriptiveMetadata.Byline = "tyomitch"; - doc.DescriptiveMetadata.Source.Title = "HABR"; - - doc.TagMetadata.Keywords.Add("парадокс берри"); - doc.TagMetadata.Keywords.Add("колмогоровская сложность"); - doc.TagMetadata.Keywords.Add("проблема останова"); - - doc.Identifier.Link = "https://habr.com/en/post/446976/"; - - var builder = new ContentBuilder(doc); - builder.EnterParagraph(); - builder.WriteText("Философ Бертран Рассел в 1908 опубликовал"); - builder.WriteLink("https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%B4%D0%BE%D0%BA%D1%81_%D0%91%D0%B5%D1%80%D1%80%D0%B8", "«парадокс Берри»"); - builder.WriteText(", который затрагивает вопрос обозначений чисел с противоположной стороны: какое самое маленькое число, для обозначения которого недостаточно восьмидесяти букв? Такое число обязано существовать: из восьмидесяти русских букв и пробелов можно составить всего 3480 обозначений, значит, с использованием восьмидесяти букв можно обозначить не более 3480 чисел.Значит, некое число, не большее чем 3480, обозначить таким образом невозможно."); - builder.EnterParagraph(); - builder.WriteText("Значит, этому числу будет соответствовать обозначение «самое маленькое число, для обозначения которого недостаточно восьмидесяти букв», в котором всего 78 букв! С одной стороны, это число обязано существовать; с другой, если это число существует, то его обозначение ему не соответствует. Парадокс!"); - builder.EnterParagraph(); - builder.WriteText("Самый простой способ отмахнуться от этого парадокса — сослаться на неформальность словесных обозначений. Мол, если бы в обозначениях допускался лишь конкретно определённый набор выражений, то «самое маленькое число, для обозначения которого недостаточно восьмидесяти букв» не было бы допустимым обозначением, тогда как практически полезные обозначения типа «факториал восьми» остались бы допустимыми."); - builder.EnterParagraph(); - builder.WriteText("Есть ли формальные способы описания последовательности (алгоритма) действий над числами? Есть, и в изобилии — их называют языками программирования. Будем вместо словесных обозначений использовать программы (например, на Python), выводящие нужные числа. Например, для пяти девяток подойдёт программа print(\"9\"*5). По-прежнему будем интересоваться самой короткой программой для заданного числа. Длину такой программы называют колмогоровской сложностью числа; это теоретический предел, до которого заданное число можно сжать."); - builder.EnterParagraph(); - builder.WriteText("Вместо парадокса Берри теперь можно рассмотреть аналогичный: какое самое маленькое число, для вывода которого недостаточно килобайтной программы?"); - builder.EnterParagraph(); - builder.WriteText("Рассуждать будем так же, как и раньше: существует 2561024 килобайтных текстов, значит, килобайтными программами можно вывести не более 2561024 чисел. Значит, некое число, не большее чем 2561024, вывести таким способом невозможно."); - builder.EnterParagraph(); - builder.WriteText("Но напишем на Python программу, которая генерирует все возможные килобайтные тексты, запускает их на выполнение, и если они выводят какое-то число — то добавляет это число в словарь достижимых. После проверки всех 2561024 возможностей, сколько бы времени это ни заняло — программа ищет, какое самое маленькое число отсутствует в словаре, и выводит это число. Кажется очевидным, что такая программа уложится в килобайт кода — и выведет то самое число, которое невозможно вывести килобайтной программой!"); - builder.EnterParagraph(); - builder.WriteText("В чём же подвох теперь? На неформальность обозначений его списать уже нельзя!"); - builder.EnterParagraph(); - builder.WriteText("Если вас смущает то, что наша программа потребует астрономического количества памяти для работы — словарь (или битовый массив) из 2561024 элементов — то можно всё то же самое осуществить и без него: для каждого из 2561024 чисел по очереди перебирать все 2561024 возможных программ, пока не найдётся подходящая. Не важно, что такой перебор продлится очень долго: после проверки менее чем (2561024)2 пар из числа и программы он ведь завершится, и найдёт то самое заветное число."); - builder.EnterParagraph(); - builder.WriteText("Или не завершится? Ведь среди всех программ, которые будут испробованы, встретится while True: pass (и её функциональные аналоги) — и дальше проверки такой программы дело уже не пойдёт!"); - builder.EnterParagraph(); - builder.WriteText("В отличие от парадокса Берри, где подвох был в неформальности обозначений, во втором случае мы имеем хорошо замаскированную переформулировку «проблемы остановки». Дело в том, что по программе невозможно за конечное время определить её вывод.В частности, колмогоровская сложность невычислима: нет никакого алгоритма, который бы позволил для заданного числа найти длину самой короткой программы, выводящей это число; а значит, нет решения и для задачи Берри — найти для заданного числа длину самого короткого словесного обозначения."); - builder.Complete(); - - var c1 = new Comment - { - Id = 0, - RefToId = -1, - Author = "exception13x", - Text = "С каких пор пробелы и запятые стали буквами? Если использовать «символов», то парадокс пропадает.", - Votes = 0, - DateTime = DateTime.Parse("2019-04-09 10:33") - }; - var c2 = new Comment - { - Id = 1, - RefToId = 0, - Author = "tyomitch", - Text = "Почему пропадает?", - Votes = 1, - DateTime = DateTime.Parse("2019-04-09 10:57") - }; - var c3 = new Comment - { - Id = 2, - RefToId = 1, - Author = "exception13x", - Text = "Потому что в фразе «самое маленькое число, для обозначения которого недостаточно восьмидесяти символов» будет 83 символа. Прошу прощения за придирки, меня просто зацепила фраза про 78 букв(которых 69 в исходной фразе)", - Votes = -1, - DateTime = DateTime.Parse("2019-04-09 12:12") - }; - var c4 = new Comment - { - Id = 3, - RefToId = 2, - Author = "kahi4", - Text = "ну поменять 80 на 100 и делов то, \"самое маленькое число, для обозначения которого недостаточно ста символов\".", - Votes = -1, - DateTime = DateTime.Parse("2019-04-09 12:50") - }; - doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c1)); - doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c2)); - doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c3)); - doc.Attachments.Add(new AttachContent("Comment", ContentType.Raw).Write(c4)); - return doc; - } - - private class Comment : - IBinarySerializable, IEquatable - { - public long Id; - public long RefToId; - - public DateTime DateTime; - public string Author; - - public string Text; - public int Votes; - - public void Deserialize(IBinaryReader reader) - { - this.Id = reader.ReadLong(); - this.RefToId = reader.ReadLong(); - this.DateTime = reader.ReadDateTime().Value; - this.Author = reader.ReadString(); - this.Text = reader.ReadString(); - this.Votes = reader.ReadInt32(); - } - - public override bool Equals(object obj) - { - return this.Equals(obj as Comment); - } - - public override int GetHashCode() - { - return this.Id.GetHashCode(); - } - - public bool Equals(Comment other) - { - if (other == null) return false; - return this.Id == other.Id && this.RefToId == other.RefToId && this.Votes == other.Votes; - } - - public void Serialize(IBinaryWriter writer) - { - writer.WriteLong(this.Id); - writer.WriteLong(this.RefToId); - writer.WriteDateTime(this.DateTime); - writer.WriteString(this.Author); - writer.WriteString(this.Text); - writer.WriteInt32(this.Votes); - } - } + MakePrimitiveTest(CompositeInstanceFactory.MakeDocument(), comparator); + } } } diff --git a/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj b/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj index 2e80525..9bd29d6 100644 --- a/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj +++ b/ZeroLevel.UnitTests/ZeroLevel.UnitTests.csproj @@ -51,12 +51,14 @@ + + diff --git a/ZeroLevel/Services/Collections/EverythingStorage.cs b/ZeroLevel/Services/Collections/EverythingStorage.cs index 4fdf58e..08da9d0 100644 --- a/ZeroLevel/Services/Collections/EverythingStorage.cs +++ b/ZeroLevel/Services/Collections/EverythingStorage.cs @@ -9,6 +9,11 @@ namespace ZeroLevel.Services.Collections public class EverythingStorage : IEverythingStorage { + public static IEverythingStorage Create() + { + return new EverythingStorage(); + } + private class ConcreteTypeRepository { private readonly IInvokeWrapper _wrapper; @@ -58,7 +63,7 @@ namespace ZeroLevel.Services.Collections return (bool)_containsKey.Invoke(_instance, key); } - public void Remove(string key) + public void Remove(string key) { _remove.Invoke(_instance, key); } @@ -67,6 +72,11 @@ namespace ZeroLevel.Services.Collections { return (T)_getter.Invoke(_instance, key); } + + public object Get(string key) + { + return _getter.Invoke(_instance, key); + } } private readonly ConcurrentDictionary _shardedRepositories = @@ -106,7 +116,7 @@ namespace ZeroLevel.Services.Collections { try { - this[typeof(T)].Remove(key); + this[typeof(T)].Remove(key); return true; } catch @@ -121,22 +131,66 @@ namespace ZeroLevel.Services.Collections public void Remove(string key) { - this[typeof(T)].Remove(key); + this[typeof(T)].Remove(key); } public T Get(string key) { return this[typeof(T)].Get(key); + } + + public void AddOrUpdate(string key, T value) + { + this[typeof(T)].InsertOrUpdate(key, value); } - public static IEverythingStorage Create() + public bool TryAdd(Type type, string key, object value) { - return new EverythingStorage(); + try + { + this[type].Insert(key, value); + return true; + } + catch + { } + return false; } - public void AddOrUpdate(string key, T value) + public bool ContainsKey(Type type, string key) { - this[typeof(T)].InsertOrUpdate(key, value); + return this[type].ContainsKey(key); + } + + public bool TryRemove(Type type, string key) + { + try + { + this[type].Remove(key); + return true; + } + catch + { } + return false; + } + + public void Add(Type type, string key, object value) + { + this[type].Insert(key, value); + } + + public void AddOrUpdate(Type type, string key, object value) + { + this[type].InsertOrUpdate(key, value); + } + + public void Remove(Type type, string key) + { + this[type].Remove(key); + } + + public object Get(Type type, string key) + { + return this[type].Get(key); } } } \ No newline at end of file diff --git a/ZeroLevel/Services/Collections/IEverythingStorage.cs b/ZeroLevel/Services/Collections/IEverythingStorage.cs index e9789b5..5104e79 100644 --- a/ZeroLevel/Services/Collections/IEverythingStorage.cs +++ b/ZeroLevel/Services/Collections/IEverythingStorage.cs @@ -1,7 +1,10 @@ -namespace ZeroLevel.Services.Collections +using System; + +namespace ZeroLevel.Services.Collections { public interface IEverythingStorage { + #region Generic bool TryAdd(string key, T value); bool ContainsKey(string key); @@ -15,5 +18,20 @@ void Remove(string key); T Get(string key); + #endregion + + bool TryAdd(Type type, string key, object value); + + bool ContainsKey(Type type, string key); + + bool TryRemove(Type type, string key); + + void Add(Type type, string key, object value); + + void AddOrUpdate(Type type, string key, object value); + + void Remove(Type type, string key); + + object Get(Type type, string key); } } \ No newline at end of file