public void EnsureTestConfigurationPassesSchemaValidation() { using var schemaReader = new StreamReader(PublishedNodesSchema); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(testConfiguration), schemaReader); Assert.True(results.All(r => r.IsValid)); }
public void IncorrectlyFormattedEndpointUrlsReturnErrors() { using var schemaReader = new StreamReader(PublishedNodesSchema); // Break the EndpointUrl by removing the `.` between `opc` and `tcp` which will // trigger a validation failure var alteredConfig = testConfiguration.Replace("opc.tcp://20.185.195.172:53530/OPCUA/SimulationServer", "opctcp://20.185.195.172:53530/OPCUA/SimulationServer"); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(alteredConfig), schemaReader); // Ensure that we failed the regex NodeID check Assert.Equal("The string value was not a match for the indicated regular expression", results.ElementAt(1).Message); }
public void EnsureTestConfigurationWithBOMHeaderPassesSchemaValidation() { using var ms = new MemoryStream(); using var writer = new StreamWriter(ms, new UTF8Encoding(true)); // Write with BOM header. writer.Write(testConfiguration); writer.Flush(); ms.Seek(0, SeekOrigin.Begin); var testConfigurationBytes = ms.ReadAsBuffer().ToArray(); using var schemaReader = new StreamReader("Default/publishednodesschema.json"); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(testConfigurationBytes, schemaReader); Assert.True(results.All(r => r.IsValid)); }
public void ByteStringNodeIdsThatAreNotByteStingsReturnErrors() { using var schemaReader = new StreamReader(PublishedNodesSchema); // Break the id of the first Node to ensure an error is thrown var alteredConfig = testConfiguration.Replace("i=1001", "b=12345"); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(alteredConfig), schemaReader); // if the default schema includes ID Value Checks if (DefaultSchemaIncludesIdValuePatterns) { // Ensure that we failed the regex NodeID check Assert.Equal("The string value was not a match for the indicated regular expression", results.ElementAt(1).Message); } }
public void ValidateTrivialStringTypeSchema() { var schema = @" { ""type"": ""object"", ""properties"": { ""prop"": { ""type"": ""string"" } } } "; var pn = @"{""prop"": ""this is a string""}"; var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(pn), new StringReader(schema)); Assert.True(results.All(r => r.IsValid)); }
public void ConfigurationFileWithLargeErrorListIsHandledSuccessfully() { using var schemaReader = new StreamReader(PublishedNodesSchema); var configFileShell = @" [ { ""EndpointUrl"": ""opc.tcp://20.185.195.172:53530/OPCUA/SimulationServer"", ""UseSecurity"": false, ""OpcNodes"": [ placeholder ] } ] "; var longNodeList = new List <string>(); // Add 10000 nodes into the temp config and make a broken replacement // of `Id` with `ID` to trigger schema failures. for (int i = 0; i < 10000; i++) { longNodeList.Add(@" { ""Id"": ""i = 1001"", ""OpcSamplingInterval"": 2000, ""OpcPublishingInterval"": 5000, } ".Replace("Id", "ID")); } var longBadConfig = configFileShell.Replace("placeholder", string.Join(",", longNodeList)); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(longBadConfig), schemaReader); // if the default schema includes ID Value Checks if (DefaultSchemaIncludesIdValuePatterns) { // Ensure that we get all 20002 errors back. Assert.Equal(20002, results.Count); // Ensure that we failed on schema checks correctly. Assert.Equal(1, results.Count(r => r.Message.Equals("Expected 1 matching subschema but found 0"))); Assert.Equal(1, results.Count(r => r.Message.Equals("Required properties [NodeId] were not present"))); Assert.Equal(10000, results.Count(r => r.Message.Equals("Required properties [Id] were not present"))); Assert.Equal(10000, results.Count(r => r.Message.Equals("Required properties [ExpandedNodeId] were not present"))); } }
public void EnsureNumericDataFailsOnStringTypeValidation() { var schema = @" { ""type"": ""object"", ""properties"": { ""prop"": { ""type"": ""string"" } } } "; var pn = @"{""prop"": 1000}"; var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(pn), new StringReader(schema)); Assert.True(results.All(r => !r.IsValid)); Assert.Equal("Value is number but should be string", results.First().Message); }
public void EnsureSchemaTrailingCommaSupportInBuffers() { var schema = @" { ""type"": ""object"", ""properties"": { ""prop"": { ""type"": ""string"" } } } "; // The following object includes a trailing comma var pn = @" { ""prop"": ""this is a string"", } "; var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(pn), new StringReader(schema)); Assert.True(results.All(r => r.IsValid)); }
// There are nuances to the use of "items" schema for arrays in JSON Schema. // Particularly the difference between "items: [{ ... }]" and "items: { ... }" // The first checks ONLY the schema of the array element in a given array index position, // whereas just object notation for "items" (e.g. '{}') will ensure that all elements are // checked against a given schema. // See: https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.4.1 public void MultipleIntNodeIdsThatAreNotIntsReturnExpectedErrors() { using var schemaReader = new StreamReader(PublishedNodesSchema); // Break the id of the second Node to ensure an error is thrown var alteredConfig = testConfiguration.Replace("i=1002", "'i=12345f'"); //Break the id of the second to last Node (#8) to ensure an error is thrown alteredConfig = alteredConfig.Replace("i=12345", "'i=12345g'"); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(alteredConfig), schemaReader); // if the default schema includes ID Value Checks if (DefaultSchemaIncludesIdValuePatterns) { Assert.NotEmpty(results); // Ensure that we failed the regex Id check on the 2nd node Assert.Equal("The string value was not a match for the indicated regular expression", results.ElementAt(1).Message); // Ensure that we failed the regex ExpandedNodeId check on the 9th node. Assert.Equal("Required properties [ExpandedNodeId] were not present", results.ElementAt(8).Message); } }
public void EnsureMultipleValidationErrorsAreFlattened() { var schema = @" { ""type"": ""object"", ""properties"": { ""prop"": { ""type"": ""string"" }, ""prop2"": { ""type"": ""integer"" } } } "; var pn = @" { ""prop"": 1000, ""prop2"":""this is a string"" } "; var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(pn), new StringReader(schema)); Assert.Equal(3, results.Count); Assert.True(results.All(r => !r.IsValid)); // Ensure that the return error messages are what we expect from the // schema validation library Assert.Equal(1, results.Where(r => !r.IsValid && r.InstanceLocation == "#" && r.SchemaLocation == "#/properties" && r.Message == null).Take(3).Count()); Assert.Equal(1, results.Where(r => !r.IsValid && r.InstanceLocation == "#/prop" && r.SchemaLocation == "#/properties/prop/type" && r.Message == "Value is number but should be string").Take(3).Count()); Assert.Equal(1, results.Where(r => !r.IsValid && r.InstanceLocation == "#/prop2" && r.SchemaLocation == "#/properties/prop2/type" && r.Message == "Value is string but should be integer").Take(3).Count()); }
public void ValidateHistoricalMixedModeSchema() { var configFileShell = @" [ { ""EndpointUrl"": ""opc.tcp://crpogace01:49320"", ""UseSecurity"": false, ""OpcNodes"": [ { ""DisplayName"": ""Kep_1_DisplayName"", ""DataSetFieldId"": ""Kep_1_DataSetFieldId"", ""Id"": ""nsu=KEPServerEX;s=Sim.CH1.SIM_CH1_TAG1\\234754a-c63-b9601"", ""OpcSamplingInterval"": 1000, ""OpcPublishingInterval"": 1000 }, { ""DisplayName"": ""Kep_2_DisplayName"", ""DataSetFieldId"": ""Kep_2_DataSetFieldId"", ""Id"": ""ns=2;s=Sim.CH1.SIM_CH1_TAG10\\2347798-c63-19401"", ""ExpandedNodeId"":""nsu=KEPServerEX;s=Sim.CH1.SIM_CH1_TAG10\\2347798-c63-19401"", ""OpcSamplingInterval"": 1000, ""OpcPublishingInterval"": 1000 } ] }, { ""EndpointUrl"": ""opc.tcp://crpogace01:51210/UA/DemoServer"", ""UseSecurity"": false, ""OpcNodes"": [ { ""DisplayName"": ""Softing_1_DisplayName"", ""DataSetFieldId"": ""Softing_1_DataSetFieldId"", ""Id"": ""http://test.org/UA/Data/#i=10847"", ""OpcSamplingInterval"": 1000, ""OpcPublishingInterval"": 1000 }, { ""DisplayName"": ""Softing_2_DisplayName"", ""DataSetFieldId"": ""Softing_2_DataSetFieldId"", ""Id"": ""nsu=http://test.org/UA/Data/;i=10848"", ""OpcSamplingInterval"": 1000, ""OpcPublishingInterval"": 1000 }, { ""DisplayName"": ""Softing_3_DisplayName"", ""DataSetFieldId"": ""Softing_3_DataSetFieldId"", ""Id"": ""ns=3;i=10849"", ""ExpandedNodeId"": ""http://test.org/UA/Data/#i=10849"", ""OpcSamplingInterval"": 1000, ""OpcPublishingInterval"": 1000 } ] } ]"; using var schemaReader = new StreamReader(PublishedNodesSchema); var validator = new JsonSchemaDotNetSchemaValidator(); var results = validator.Validate(Encoding.UTF8.GetBytes(configFileShell), schemaReader); if (!DefaultSchemaIncludesIdValuePatterns) { Assert.True(results.First().IsValid); } else { Assert.Equal(12, results.Count()); // Ensure that we failed the regex Id check on the 2nd node Assert.Equal("Expected 1 matching subschema but found 0", results.ElementAt(1).Message); // Ensure that we failed the regex ExpandedNodeId check on the 9th node. Assert.Equal("The string value was not a match for the indicated regular expression", results.ElementAt(2).Message); } }