Example #1
0
        public void AddParameter()
        {
            var message   = new MessageSchema("A");
            var parameter = new ParameterSchema("X", new RecordSchema("Y"));

            Assert.DoesNotThrow(
                () => message.AddParameter(parameter)
                );

            Assert.Throws(
                typeof(AvroException),
                () => message.AddParameter(parameter)
                );
        }
        public void MissingMessageType()
        {
            var protocol = new AvroProtocol();
            var record   = new RecordSchema("Name");
            var message  = new MessageSchema("M");

            message.AddParameter(new ParameterSchema("par", record));

            Assert.Throws(
                typeof(AvroException),
                () => protocol.AddMessage(message)
                );
        }
            public IEnumerator GetEnumerator()
            {
                var record01 = new RecordSchema()
                {
                    Name = "TestRecord01"
                };
                var record02 = new RecordSchema()
                {
                    Name = "TestRecord02"
                };

                var errord01 = new ErrorSchema()
                {
                    Name = "TestError01"
                };
                var errord02 = new ErrorSchema()
                {
                    Name = "TestError02"
                };


                var protocol01 = new AvroProtocol
                {
                    Name = "ProtocolName"
                };

                yield return(new object[] {
                    protocol01,
                    @"{""protocol"":""ProtocolName""}",
                    @"{ ""protocol"": ""ProtocolName"" }",
                    @"{ ""namespace"": """", ""protocol"": ""ProtocolName"", ""doc"": """", ""types"": [], ""messages"": {} }"
                });

                var protocol02 = new AvroProtocol
                {
                    Name      = "ProtocolName",
                    Namespace = "Test.Namespace"
                };

                yield return(new object[] {
                    protocol02,
                    @"{""protocol"":""Test.Namespace.ProtocolName""}",
                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"" }",
                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": """", ""types"": [], ""messages"": {} }"
                });

                var protocol03 = new AvroProtocol
                {
                    Name      = "ProtocolName",
                    Namespace = "Test.Namespace",
                    Doc       = "Test Documentation"
                };

                yield return(new object[] {
                    protocol03,
                    @"{""protocol"":""Test.Namespace.ProtocolName""}",
                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"" }",
                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"", ""types"": [], ""messages"": {} }"
                });

                var protocol04 = new AvroProtocol
                {
                    Name      = "ProtocolName",
                    Namespace = "Test.Namespace",
                    Doc       = "Test Documentation"
                };

                protocol04.AddType(record01);
                protocol04.AddType(record02);
                protocol04.AddType(errord01);
                protocol04.AddType(errord02);

                yield return(new object[] {
                    protocol04,
                    @"{""protocol"":""Test.Namespace.ProtocolName"",""types"":" +
                    @"[{""name"":""Test.Namespace.TestRecord01"",""type"":""record"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestRecord02"",""type"":""record"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestError01"",""type"":""error"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestError02"",""type"":""error"",""fields"":[]}" +
                    @"]}",

                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"", ""types"": " +
                    @"[{ ""type"": ""record"", ""name"": ""TestRecord01"", ""fields"": [] }, " +
                    @"{ ""type"": ""record"", ""name"": ""TestRecord02"", ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError01"", ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError02"", ""fields"": [] }" +
                    @"] }",

                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"", ""types"": " +
                    @"[{ ""type"": ""record"", ""name"": ""TestRecord01"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""record"", ""name"": ""TestRecord02"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError01"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError02"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] " +
                    @"}]," +
                    @" ""messages"": {} }"
                });

                var protocol05 = new AvroProtocol
                {
                    Name      = "ProtocolName",
                    Namespace = "Test.Namespace",
                    Doc       = "Test Documentation"
                };

                protocol05.AddType(record01);
                protocol05.AddType(record02);
                protocol05.AddType(errord01);
                protocol05.AddType(errord02);

                var message01 = new MessageSchema("M01")
                {
                    Doc = "Test Doc 01"
                };

                message01.AddParameter(new ParameterSchema("p01", record01));
                message01.AddParameter(new ParameterSchema("p02", record02));
                message01.AddError(errord01);
                message01.AddError(errord02);
                message01.Response = new DoubleSchema();

                var message02 = new MessageSchema("M02");

                message02.AddParameter(new ParameterSchema("p01", record01));
                message02.AddError(errord01);
                message02.Oneway = true;

                protocol05.AddMessage(message01);
                protocol05.AddMessage(message02);

                yield return(new object[] {
                    protocol05,
                    @"{""protocol"":""Test.Namespace.ProtocolName"",""types"":" +
                    @"[{""name"":""Test.Namespace.TestRecord01"",""type"":""record"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestRecord02"",""type"":""record"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestError01"",""type"":""error"",""fields"":[]}," +
                    @"{""name"":""Test.Namespace.TestError02"",""type"":""error"",""fields"":[]}" +
                    @"]," +
                    @"""messages"":{" +
                    @"""M01"":{" +
                    @"""request"":[{""name"":""p01"",""type"":""Test.Namespace.TestRecord01""},{""name"":""p02"",""type"":""Test.Namespace.TestRecord02""}]," +
                    @"""response"":""double""," +
                    @"""errors"":[""Test.Namespace.TestError01"",""Test.Namespace.TestError02""]" +
                    @"}," +
                    @"""M02"":{" +
                    @"""request"":[{""name"":""p01"",""type"":""Test.Namespace.TestRecord01""}]," +
                    @"""errors"":[""Test.Namespace.TestError01""]," +
                    @"""one-way"":true" +
                    @"}}}",

                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"", ""types"": " +
                    @"[{ ""type"": ""record"", ""name"": ""TestRecord01"", ""fields"": [] }, " +
                    @"{ ""type"": ""record"", ""name"": ""TestRecord02"", ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError01"", ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError02"", ""fields"": [] }" +
                    @"], " +
                    @"""messages"": {" +
                    @"""M01"": {" +
                    @"""doc"": ""Test Doc 01"", " +
                    @"""request"": [{ ""name"": ""p01"", ""type"": ""TestRecord01"" }, { ""name"": ""p02"", ""type"": ""TestRecord02"" }], " +
                    @"""response"": ""double"", " +
                    @"""errors"": [""TestError01"", ""TestError02""]" +
                    @"}, " +
                    @"""M02"": {" +
                    @"""request"": [{ ""name"": ""p01"", ""type"": ""TestRecord01"" }], " +
                    @"""errors"": [""TestError01""], " +
                    @"""one-way"": true" +
                    @"}} }",

                    @"{ ""namespace"": ""Test.Namespace"", ""protocol"": ""ProtocolName"", ""doc"": ""Test Documentation"", ""types"": " +
                    @"[{ ""type"": ""record"", ""name"": ""TestRecord01"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""record"", ""name"": ""TestRecord02"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError01"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }, " +
                    @"{ ""type"": ""error"", ""name"": ""TestError02"", ""namespace"": ""Test.Namespace"", ""doc"": """", ""aliases"": [], ""fields"": [] }" +
                    @"], " +
                    @"""messages"": {" +
                    @"""M01"": {" +
                    @"""doc"": ""Test Doc 01"", " +
                    @"""request"": [{ ""name"": ""p01"", ""type"": ""Test.Namespace.TestRecord01"" }, { ""name"": ""p02"", ""type"": ""Test.Namespace.TestRecord02"" }], " +
                    @"""response"": { ""type"": ""double"" }, " +
                    @"""errors"": [""Test.Namespace.TestError01"", ""Test.Namespace.TestError02""], " +
                    @"""one-way"": false" +
                    @"}, " +
                    @"""M02"": {" +
                    @"""doc"": """", " +
                    @"""request"": [{ ""name"": ""p01"", ""type"": ""Test.Namespace.TestRecord01"" }], " +
                    @"""response"": null, " +
                    @"""errors"": [""Test.Namespace.TestError01""], " +
                    @"""one-way"": true" +
                    @"}} }"
                });
            }
        private static IList <MessageSchema> ParseMessages(JObject jObject, IDictionary <string, NamedSchema> types, Stack <string> enclosingNamespace)
        {
            var keys = new HashSet <string>()
            {
                "request", "response"
            };
            var optionalKeys = new HashSet <string>()
            {
                "doc", "errors", "one-way"
            };
            var messages = new List <MessageSchema>();

            foreach (var item in JsonUtil.GetKeyValues(jObject))
            {
                var name   = item.Key;
                var jToken = item.Value;

                JsonUtil.AssertKeys(item.Value, keys, optionalKeys, out _);

                var message  = new MessageSchema(name);
                var request  = JsonUtil.GetValue <JArray>(jToken, "request");
                var response = JsonUtil.GetValue <JToken>(jToken, "response");

                foreach (var requestParameter in ParseRequests(request, types, enclosingNamespace))
                {
                    message.AddParameter(requestParameter);
                }
                message.Response = ParseSchema(response, types, enclosingNamespace);

                if (JsonUtil.TryGetValue <string>(jToken, "doc", out var doc))
                {
                    message.Doc = doc;
                }
                if (JsonUtil.TryGetValue <bool>(jToken, "one-way", out var oneway))
                {
                    if (oneway && !(message.Response is NullSchema))
                    {
                        throw new AvroParseException("One way messages must have a 'null' response");
                    }
                    else
                    {
                        message.Oneway = oneway;
                    }
                }

                if (JsonUtil.TryGetValue <JArray>(jToken, "errors", out var errors))
                {
                    foreach (var error in errors)
                    {
                        if (error.Type != JTokenType.String)
                        {
                            throw new AvroParseException($"Declared type must be a string.");
                        }

                        var declaredType = QualifyName(error.ToString(), enclosingNamespace);
                        if (!types.TryGetValue(declaredType, out var errorType))
                        {
                            throw new AvroParseException($"'{declaredType}' is not a declared type.");
                        }
                        if (!(errorType is ErrorSchema))
                        {
                            throw new AvroParseException($"'{declaredType}' is not an error type.");
                        }
                        message.AddError(errorType as ErrorSchema);
                    }
                }

                messages.Add(message);
            }
            return(messages);
        }