#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2016 Google Inc. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #endregion using System; using Google.Protobuf.TestProtos; using NUnit.Framework; namespace Google.Protobuf.WellKnownTypes { public class FieldMaskTest { [Test] [TestCase("foo__bar")] [TestCase("foo_3_ar")] [TestCase("fooBar")] public void ToString_Invalid(string input) { var mask = new FieldMask { Paths = { input } }; var text = mask.ToString(); // More specific test below Assert.That(text, Does.Contain("@warning")); Assert.That(text, Does.Contain(input)); } [Test] public void ToString_Invalid_Precise() { var mask = new FieldMask { Paths = { "x", "foo__bar", @"x\y" } }; Assert.AreEqual( "{ \"@warning\": \"Invalid FieldMask\", \"paths\": [ \"x\", \"foo__bar\", \"x\\\\y\" ] }", mask.ToString()); } [Test] public void IsValid() { Assert.IsTrue(FieldMask.IsValid("payload")); Assert.IsFalse(FieldMask.IsValid("nonexist")); Assert.IsTrue(FieldMask.IsValid("payload.single_int32")); Assert.IsTrue(FieldMask.IsValid("payload.repeated_int32")); Assert.IsTrue(FieldMask.IsValid("payload.single_nested_message")); Assert.IsTrue(FieldMask.IsValid("payload.repeated_nested_message")); Assert.IsFalse(FieldMask.IsValid("payload.nonexist")); Assert.IsTrue(FieldMask.IsValid(FieldMask.FromString("payload"))); Assert.IsFalse(FieldMask.IsValid(FieldMask.FromString("nonexist"))); Assert.IsFalse(FieldMask.IsValid(FieldMask.FromString("payload,nonexist"))); Assert.IsTrue(FieldMask.IsValid(NestedTestAllTypes.Descriptor, "payload")); Assert.IsFalse(FieldMask.IsValid(NestedTestAllTypes.Descriptor, "nonexist")); Assert.IsTrue(FieldMask.IsValid(NestedTestAllTypes.Descriptor, FieldMask.FromString("payload"))); Assert.IsFalse(FieldMask.IsValid(NestedTestAllTypes.Descriptor, FieldMask.FromString("nonexist"))); Assert.IsTrue(FieldMask.IsValid("payload.single_nested_message.bb")); // Repeated fields cannot have sub-paths. Assert.IsFalse(FieldMask.IsValid("payload.repeated_nested_message.bb")); // Non-message fields cannot have sub-paths. Assert.IsFalse(FieldMask.IsValid("payload.single_int32.bb")); } [Test] [TestCase(new string[] { }, "\"\"")] [TestCase(new string[] { "foo" }, "\"foo\"")] [TestCase(new string[] { "foo", "bar" }, "\"foo,bar\"")] [TestCase(new string[] { "", "foo", "", "bar", "" }, "\",foo,,bar,\"")] public void ToString(string[] input, string expectedOutput) { FieldMask mask = new FieldMask(); mask.Paths.AddRange(input); Assert.AreEqual(expectedOutput, mask.ToString()); } [Test] [TestCase("", new string[] { })] [TestCase("foo", new string[] { "foo" })] [TestCase("foo,bar.baz", new string[] { "foo", "bar.baz" })] [TestCase(",foo,,bar,", new string[] { "foo", "bar" })] public void FromString(string input, string[] expectedOutput) { FieldMask mask = FieldMask.FromString(input); Assert.AreEqual(expectedOutput.Length, mask.Paths.Count); for (int i = 0; i < expectedOutput.Length; i++) { Assert.AreEqual(expectedOutput[i], mask.Paths[i]); } } [Test] public void FromString_Validated() { // Check whether the field paths are valid if a class parameter is provided. Assert.DoesNotThrow(() => FieldMask.FromString(",payload")); Assert.Throws(() => FieldMask.FromString("payload,nonexist")); } [Test] [TestCase(new int[] { }, new string[] { })] [TestCase(new int[] { TestAllTypes.SingleInt32FieldNumber }, new string[] { "single_int32" })] [TestCase(new int[] { TestAllTypes.SingleInt32FieldNumber, TestAllTypes.SingleInt64FieldNumber }, new string[] { "single_int32", "single_int64" })] public void FromFieldNumbers(int[] input, string[] expectedOutput) { FieldMask mask = FieldMask.FromFieldNumbers(input); Assert.AreEqual(expectedOutput.Length, mask.Paths.Count); for (int i = 0; i < expectedOutput.Length; i++) { Assert.AreEqual(expectedOutput[i], mask.Paths[i]); } } [Test] public void FromFieldNumbers_Invalid() { Assert.Throws(() => { int invalidFieldNumber = 1000; FieldMask.FromFieldNumbers(invalidFieldNumber); }); } [Test] [TestCase(new string[] { }, "\"\"")] [TestCase(new string[] { "foo" }, "\"foo\"")] [TestCase(new string[] { "foo", "bar" }, "\"foo,bar\"")] [TestCase(new string[] { "", "foo", "", "bar", "" }, "\",foo,bar\"")] public void Normalize(string[] input, string expectedOutput) { FieldMask mask = new FieldMask(); mask.Paths.AddRange(input); FieldMask result = mask.Normalize(); Assert.AreEqual(expectedOutput, result.ToString()); } [Test] public void Union() { // Only test a simple case here and expect // {@link FieldMaskTreeTest#AddFieldPath} to cover all scenarios. FieldMask mask1 = FieldMask.FromString("foo,bar.baz,bar.quz"); FieldMask mask2 = FieldMask.FromString("foo.bar,bar"); FieldMask result = mask1.Union(mask2); Assert.AreEqual(2, result.Paths.Count); Assert.Contains("bar", result.Paths); Assert.Contains("foo", result.Paths); Assert.That(result.Paths, Has.No.Member("bar.baz")); Assert.That(result.Paths, Has.No.Member("bar.quz")); Assert.That(result.Paths, Has.No.Member("foo.bar")); } [Test] public void Union_UsingVarArgs() { FieldMask mask1 = FieldMask.FromString("foo"); FieldMask mask2 = FieldMask.FromString("foo.bar,bar.quz"); FieldMask mask3 = FieldMask.FromString("bar.quz"); FieldMask mask4 = FieldMask.FromString("bar"); FieldMask result = mask1.Union(mask2, mask3, mask4); Assert.AreEqual(2, result.Paths.Count); Assert.Contains("bar", result.Paths); Assert.Contains("foo", result.Paths); Assert.That(result.Paths, Has.No.Member("foo.bar")); Assert.That(result.Paths, Has.No.Member("bar.quz")); } [Test] public void Intersection() { // Only test a simple case here and expect // {@link FieldMaskTreeTest#IntersectFieldPath} to cover all scenarios. FieldMask mask1 = FieldMask.FromString("foo,bar.baz,bar.quz"); FieldMask mask2 = FieldMask.FromString("foo.bar,bar"); FieldMask result = mask1.Intersection(mask2); Assert.AreEqual(3, result.Paths.Count); Assert.Contains("foo.bar", result.Paths); Assert.Contains("bar.baz", result.Paths); Assert.Contains("bar.quz", result.Paths); Assert.That(result.Paths, Has.No.Member("foo")); Assert.That(result.Paths, Has.No.Member("bar")); } [Test] public void Merge() { // Only test a simple case here and expect // {@link FieldMaskTreeTest#Merge} to cover all scenarios. FieldMask fieldMask = FieldMask.FromString("payload"); NestedTestAllTypes source = new NestedTestAllTypes { Payload = new TestAllTypes { SingleInt32 = 1234, SingleFixed64 = 4321 } }; NestedTestAllTypes destination = new NestedTestAllTypes(); fieldMask.Merge(source, destination); Assert.AreEqual(1234, destination.Payload.SingleInt32); Assert.AreEqual(4321, destination.Payload.SingleFixed64); destination = new NestedTestAllTypes { Payload = new TestAllTypes { SingleInt32 = 4321, SingleInt64 = 5678 } }; fieldMask.Merge(source, destination); Assert.AreEqual(1234, destination.Payload.SingleInt32); Assert.AreEqual(5678, destination.Payload.SingleInt64); Assert.AreEqual(4321, destination.Payload.SingleFixed64); } } }