public void Database_NewtonsoftCompatibility() { // Test that basic Database, Table, and Row types can successfully roundtrip via Newtonsoft.Json serialization by default. // These use generated JsonConverter classes to serialize using safe constructors and good default behaviors. V1.Community v1 = new V1.Community(); v1.People = new List <V1.Person>(); v1.People.Add(new V1.Person() { Age = 39, Name = "Scott" }); v1.People.Add(new V1.Person() { Age = 36, Name = "Adam" }); string serializeToPath = Path.GetFullPath("Community.V1.json"); AsJson.Save(serializeToPath, v1, verbose: true); V1.Community roundTrip = AsJson.Load <V1.Community>(serializeToPath); CollectionReadVerifier.VerifySame(v1.People, roundTrip.People); AsJson.Save(serializeToPath, v1, verbose: true); roundTrip = AsJson.Load <V1.Community>(serializeToPath); CollectionReadVerifier.VerifySame(v1.People, roundTrip.People); // Verify V2 object model will load community (post-replacements make Person parsing non-strict) V2.Community v2 = AsJson.Load <V2.Community>(serializeToPath); Assert.Equal(2, v2.People.Count); Assert.Equal(v1.People[0].Name, v2.People[0].Name); }
public void Database_NewtonsoftCompatibility() { // Test that basic Database, Table, and Row types can successfully roundtrip via Newtonsoft.Json serialization by default. // These use generated JsonConverter classes to serialize using safe constructors and good default behaviors. V1.Community v1 = new V1.Community(); v1.People.Add(new V1.Person() { Age = 39, Name = "Scott" }); v1.People.Add(new V1.Person() { Age = 36, Name = "Adam" }); string serializeToPath = Path.GetFullPath("Community.V1.json"); AsJson.Save(serializeToPath, v1, verbose: true); V1.Community roundTrip = AsJson.Load <V1.Community>(serializeToPath); CollectionReadVerifier.VerifySame(v1.People, roundTrip.People); AsJson.Save(serializeToPath, v1, verbose: true); roundTrip = AsJson.Load <V1.Community>(serializeToPath); CollectionReadVerifier.VerifySame(v1.People, roundTrip.People); }
internal static void VerifyRoundTrip <T>(ArraySlice <T> slice, T[] copyToTargetArray) where T : unmanaged, IEquatable <T> { ArraySlice <T> roundTripped = TreeSerializer.RoundTrip(slice, TreeFormat.Binary); CollectionReadVerifier.VerifySame <T>(slice, roundTripped); VerifyCopyTo <T>(roundTripped, copyToTargetArray); }
public void ArraySliceTests_Basics() { int[] sample = Enumerable.Range(100, 50).ToArray(); int[] copyToTarget = new int[100]; ArraySlice <int> slice; // Empty ArraySlice slice = ArraySlice <int> .Empty; slice.Trim(); Assert.Empty(slice); Assert.True(slice == ArraySlice <int> .Empty); Assert.False(slice != ArraySlice <int> .Empty); VerifyCopyTo <int>(slice, copyToTarget); VerifyRoundTrip <int>(slice, copyToTarget); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Binary)); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Json)); // Whole Array slice = new ArraySlice <int>(sample); Assert.Equal(sample.Length, slice.Count); Assert.Equal(sample, slice); Assert.Equal(sample[10], slice[10]); VerifyCopyTo <int>(slice, copyToTarget); VerifyRoundTrip <int>(slice, copyToTarget); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Binary)); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Json)); // Array slice-to-end slice = new ArraySlice <int>(sample, index: 10); Assert.Equal(sample.Length - 10, slice.Count); Assert.Equal(sample[20], slice[10]); Assert.False(slice.Equals(sample)); VerifyCopyTo <int>(slice, copyToTarget); VerifyRoundTrip <int>(slice, copyToTarget); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Binary)); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Json)); // Array slice slice = new ArraySlice <int>(sample, index: 10, length: 20); Assert.Equal(20, slice.Count); Assert.Equal(sample[10], slice[0]); VerifyCopyTo <int>(slice, copyToTarget); VerifyRoundTrip <int>(slice, copyToTarget); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Binary)); CollectionReadVerifier.VerifySame(slice, TreeSerializer.RoundTrip(slice, TreeFormat.Json)); // Bounds checks Assert.Throws <ArgumentNullException>(() => new ArraySlice <int>(null, 0, 0)); // Array null Assert.Throws <ArgumentOutOfRangeException>(() => new ArraySlice <int>(sample, -1, 0)); // index < 0 Assert.Throws <ArgumentOutOfRangeException>(() => new ArraySlice <int>(sample, sample.Length + 1, 0)); // index > array.Length Assert.Throws <ArgumentOutOfRangeException>(() => new ArraySlice <int>(sample, 0, sample.Length + 1)); // length too long Assert.Throws <ArgumentOutOfRangeException>(() => new ArraySlice <int>(sample, 2, sample.Length + 3)); // Clear slice.Clear(); Assert.Empty(slice); }
public void Database_ReplaceColumn() { // Test saving a database and then loading it into a different object model with added and removed columns. V1.Community v1 = new V1.Community(); v1.People.Add(new V1.Person() { Age = 39, Name = "Scott" }); v1.People.Add(new V1.Person() { Age = 36, Name = "Adam" }); string filePath = "People.bsoa.bin"; // Save V1 (Age and Name) v1.DB.Save(filePath, TreeFormat.Binary); // Load as V2 (BirthDate and Name) V2.Community v2 = new V2.Community(); v2.DB.Load(filePath, TreeFormat.Binary); // Verify row count the same, Name loaded properly Assert.Equal(v1.People.Count, v2.People.Count); Assert.Equal(v1.People[0].Name, v2.People[0].Name); DateTime birthdate = DateTime.Parse("1981-01-01").ToUniversalTime(); v2.People[0].Birthdate = birthdate; // Verify new database serializes new column V2.Community v2RoundTrip = new V2.Community(); v2.DB.Save(filePath, TreeFormat.Binary); v2RoundTrip.DB.Load(filePath, TreeFormat.Binary); Assert.Equal(birthdate, v2RoundTrip.People[0].Birthdate); CollectionReadVerifier.VerifySame(v2.People, v2RoundTrip.People); // Load *new format* into V1 object model V1.Community v1RoundTrip = new V1.Community(); v1RoundTrip.DB.Load(filePath, TreeFormat.Binary); // Verify unchanged columns come back Assert.Equal(v1.People.Count, v1RoundTrip.People.Count); Assert.Equal(v1.People[0].Name, v1RoundTrip.People[0].Name); // Verify Age empty Assert.Equal(0, v1RoundTrip.People[0].Age); // Read with TreeSerializationSettings.Strict and verify error Assert.Throws <IOException>(() => v1RoundTrip.DB.Load(filePath, TreeFormat.Binary, new BSOA.IO.TreeSerializationSettings() { Strict = true })); }
public void Database_Basics() { V1.Community community = new V1.Community(); community.People = new List <V1.Person>(); community.People.Add(new V1.Person() { Age = 39, Name = "Scott" }); community.People.Add(new V1.Person() { Age = 36, Name = "Adam" }); // Use ReadOnlyList.VerifySame to check count, enumerators, and indexer community.DB.Save("V1.Community.bsoa", TreeFormat.Binary); V1.Community roundTripped = new V1.Community(); roundTripped.DB.Load("V1.Community.bsoa", TreeFormat.Binary); CollectionReadVerifier.VerifySame(community.People, roundTripped.People); // Try loading database with size diagnostics TreeDiagnostics diagnostics = TreeSerializer.Diagnostics(community.DB, () => new V1.Community().DB, TreeFormat.Binary); // Verify table and column names in diagnostics string text = diagnostics.ToString(); Assert.Contains("Person", text); Assert.Contains("Age", text); Assert.Contains("Name", text); // Verify Person has two columns, Write doesn't throw Assert.Equal("Person", diagnostics.Children[0].Name); Assert.Equal(Names.Columns, diagnostics.Children[0].Children[0].Name); Assert.Equal(2, diagnostics.Children[0].Children[0].Children.Count); diagnostics.Write(Console.Out, 3); // Verify Trim doesn't throw (results not visible) community.DB.Trim(); CollectionReadVerifier.VerifySame(community.People, roundTripped.People); // Verify Copy constructor recursively copies (List.SetTo -> LocalIndex -> CopyFrom construction) V1.Community copy = new V1.Community(community); CollectionReadVerifier.VerifySame(community.People, copy.People); community.People[0].Age += 10; Assert.NotEqual(community.People[0].Age, copy.People[0].Age); // Verify Database.Clear works community.DB.Clear(); var people = community.People; Assert.True(people == null || people.Count == 0); }
public void IndirectCollection_Basics() { // Note: ColumnDictionary now sorts keys internally, so collections will come in sorted order, not insertion order IDictionary <string, string> row = DictionaryColumnTests.SampleRow(); row["City"] = "Redmond"; row["Name"] = "Scott"; List <string> keys = new List <string>() { "City", "Name" }; List <string> values = new List <string>() { "Redmond", "Scott" }; IndirectCollection <string> collection = (IndirectCollection <string>)row.Keys; // Count Assert.Equal(2, collection.Count); // Enumeration CollectionReadVerifier.VerifySame(keys, (IndirectCollection <string>)row.Keys); CollectionReadVerifier.VerifySame(values, (IndirectCollection <string>)row.Values); // Read-Only-ness Assert.True(collection.IsReadOnly); Assert.Throws <NotSupportedException>(() => collection.Add("New")); Assert.Throws <NotSupportedException>(() => collection.Remove("Name")); Assert.Throws <NotSupportedException>(() => collection.Clear()); // Contains Assert.True(true == collection.Contains("Name")); Assert.True(false == collection.Contains("New")); // CopyTo string[] names = new string[3]; collection.CopyTo(names, 1); Assert.Equal("City", names[1]); Assert.Equal("Name", names[2]); Assert.Throws <ArgumentNullException>(() => collection.CopyTo(null, 0)); Assert.Throws <ArgumentOutOfRangeException>(() => collection.CopyTo(names, -1)); Assert.Throws <ArgumentException>(() => collection.CopyTo(names, 2)); }
public void ColumnDictionary_Basics() { string sampleName = "Name"; string sampleValue = "Scott"; string retrievedValue = null; string secondName = "City"; string secondValue = "Redmond"; string unusedName = "Unused"; Dictionary <string, string> expected = new Dictionary <string, string>(); ColumnDictionary <string, string> row = DictionaryColumnTests.SampleRow(); Assert.True(0 == ColumnDictionary <string, string> .Empty.Count); Assert.False(row.IsReadOnly); // Test Empty Dictionary Assert.False(row.TryGetValue(sampleName, out retrievedValue)); Assert.False(row.ContainsKey(sampleName)); Assert.False(row.Remove(sampleName)); Assert.True(0 == row.Count); Assert.Empty(row.Keys); Assert.Empty(row.Values); // Add a single value and test results expected[sampleName] = sampleValue; row[sampleName] = sampleValue; CollectionReadVerifier.VerifySame(expected, row); CollectionReadVerifier.VerifySame(expected.Keys, row.Keys); CollectionReadVerifier.VerifySame(expected.Values, row.Values); // Add a second value and verify expected.Add(secondName, secondValue); row.Add(new KeyValuePair <string, string>(secondName, secondValue)); CollectionReadVerifier.VerifySame(expected, row); CollectionReadVerifier.VerifySame(expected.Keys, row.Keys); CollectionReadVerifier.VerifySame(expected.Values, row.Values); // Negative (missing item / already added item) cases Assert.True(false == row.Contains(new KeyValuePair <string, string>(sampleName, secondValue))); Assert.True(false == row.Contains(new KeyValuePair <string, string>(unusedName, sampleValue))); Assert.True(false == row.ContainsKey(unusedName)); Assert.Throws <KeyNotFoundException>(() => row[unusedName]); Assert.Throws <ArgumentException>(() => row.Add(new KeyValuePair <string, string>(sampleName, secondValue))); // Change value and verify, then change back Assert.Equal(expected[sampleName], row[sampleName]); expected[sampleName] = secondValue; row[sampleName] = secondValue; Assert.Equal(expected[sampleName], row[sampleName]); CollectionReadVerifier.VerifySame(expected, row); CollectionReadVerifier.VerifySame(expected.Keys, row.Keys); CollectionReadVerifier.VerifySame(expected.Values, row.Values); expected[sampleName] = sampleValue; row[sampleName] = sampleValue; Assert.Equal(expected[sampleName], row[sampleName]); // Remove Assert.True(row.Remove(secondName)); Assert.False(row.Remove(secondName)); Assert.False(row.ContainsKey(secondName)); Assert.False(row.Remove(new KeyValuePair <string, string>(unusedName, sampleValue))); Assert.False(row.Remove(new KeyValuePair <string, string>(sampleName, secondValue))); Assert.True(row.Remove(new KeyValuePair <string, string>(sampleName, sampleValue))); Assert.Empty(row); // SetTo row.SetTo(expected); CollectionReadVerifier.VerifySame <KeyValuePair <string, string> >(expected, row); // Create another Dictionary with the same values inserted in a different order ColumnDictionary <string, string> row2 = DictionaryColumnTests.SampleRow(); row2[secondName] = secondValue; row2[sampleName] = sampleValue; // Test Equals and GetHashCode CollectionReadVerifier.VerifyEqualityMembers <ColumnDictionary <string, string> >(row, row2); // Test equality operators Assert.True(row == row2); Assert.False(row != row2); Assert.False(row == null); Assert.True(row != null); Assert.False(null == row); Assert.True(null != row); // GetHashCode handles null key/values safely row[null] = null; Assert.Equal(row.GetHashCode(), row2.GetHashCode()); // Verify other collection manipulation // NOTE: Must use unique keys, because Add(KeyValuePair) will throw for a duplicate key CollectionChangeVerifier.VerifyCollection(row, (i) => new KeyValuePair <string, string>(i.ToString(), i.ToString())); if (!Debugger.IsAttached) { Assert.Throws <IndexOutOfRangeException>(() => ColumnDictionary <string, string> .Get(null, -1)); } }
public void TypedList_Basics() { Community c = new Community(); List <Person> people = new List <Person> { new Person(c) { Name = "One" }, new Person(c) { Name = "Two" }, new Person(c) { Name = "Three" } }; // Null by default Assert.Null(c.People); // Settable to Empty c.People = Array.Empty <Person>(); TypedList <Person> list = (TypedList <Person>)c.People; Assert.Empty(list); list.Add(people[0]); Assert.Single(list); list.Add(people[1]); list.Add(people[2]); CollectionReadVerifier.VerifySame(people, list); // SetTo self works properly list.SetTo(list); CollectionReadVerifier.VerifySame(people, list); // SetTo null works list.SetTo(null); Assert.Empty(list); // SetTo other works list.SetTo(people); CollectionReadVerifier.VerifySame(people, list); // Test Equality members CollectionReadVerifier.VerifyEqualityMembers(list, list); // Test equality operators #pragma warning disable CS1718 // Comparison made to same variable Assert.True(list == list); Assert.False(list != list); #pragma warning restore CS1718 // Comparison made to same variable Assert.False(list == null); Assert.True(list != null); Assert.False(null == list); Assert.True(null != list); // SetTo empty works list.SetTo(new List <Person>()); Assert.Empty(list); CollectionChangeVerifier.VerifyList(c.People, (i) => new Person(c) { Age = (byte)i }); // Set null IList <Person> cachedPeople = c.People; c.People = null; Assert.Null(c.People); Assert.Equal(0, cachedPeople.Count); // SetTo TypedList from another DB/Table Community c2 = new Community(); c2.People = new List <Person>(); c2.People.Add(new Person(c2) { Name = "Other" }); list.SetTo(c2.People); Assert.Equal("Other", list[0].Name); }