Beispiel #1
0
        private static List<Verification> SetupVerifications(Setup setup, EventStream stream, Mono.CSharp.Evaluator evaluator, string tab)
        {
            var verifications = new List<Verification>();

            // First set the verifications.
            foreach (var verifyList in setup.Verify)
            {
                var verifyBuilder = new StringBuilder(@"
            var func = new Func<IEventStream, IObservable<Unit>>(stream =>
            ");

                var filters = new List<string>();
                for (int i = 0; i < verifyList.Then.Count; i++)
                {
                    var var = ((char)(97 + i)).ToString(); // 97 == 'a'
                    var verify = verifyList.Then[i];
                    var topicType = setup.Topics.Find(verify.Topic);
                    Assert.True(topicType != TopicType.Unknown, "Undeclared topic '" + verify.Topic + "'");

                    var codeType = Brain.TopicCodeTypes.Find(topicType);

                    Assert.False((topicType == TopicType.Void && verify.Value != null),
                        string.Format("Cannot specify a value to compare for void topic '{0}' in verification '{1}'", verify.Topic, verify));

                    verifyBuilder.Append(tab).AppendLine("from {var} in stream.Commands<{type}>(\"{topic}\", \"{devices}\")".FormatWith(
                        new { var = var, type = codeType, topic = verify.Topic, devices = verify.Devices }));

                    // For void topics there's no need to filter out payload values,
                    // just getting a message with the given topic satisfies the query.
                    if (topicType != TopicType.Void)
                    {
                        // In this case we need to take into account the value
                        // received.
                        filters.Add("{var} == {value}".FormatWith(
                            new { var = var, value = FormatValue(topicType, verify.Value) }));
                    }
                }

                if (filters.Count > 0)
                {
                    verifyBuilder.Append(tab).Append("where ");
                    if (verifyList.Negate)
                    {
                        verifyBuilder
                            .Append("!(")
                            .Append(string.Join(" && ", filters))
                            .AppendLine(")");
                    }
                    else
                    {
                        verifyBuilder.AppendLine(string.Join(" && ", filters));
                    }
                }

                verifyBuilder
                    .Append(tab).AppendLine("select Unit.Default")
                    .AppendLine(");")
                    .AppendLine()
                    .Append("func;");

                Tracer.Get<BrainExercise>().Verbose("Buit verification query: " + verifyBuilder.ToString());

                var func = (Func<IEventStream, IObservable<Unit>>)evaluator.Evaluate(verifyBuilder.ToString());
                var query = func(stream);
                var verification = new Verification
                {
                    Expression = (verifyList.Negate ? "!" : "") +
                        string.Join(" and ", verifyList.Then.Select(t => t.ToString())),
                    Succeeded = verifyList.Negate,
                };

                if (verifyList.Negate)
                    query.Subscribe(_ => verification.Succeeded = false);
                else
                    query.Subscribe(_ => verification.Succeeded = true);

                verifications.Add(verification);
            }

            return verifications;
        }
Beispiel #2
0
        private void Run(Setup setup)
        {
            var stream = new EventStream();
            stream.Of<IEventPattern<IDevice, IImpulse>>().Subscribe(x => Tracer.Get<BrainExercise>().Info("Impulse from {0}: {1}", x.Sender.Id, x.EventArgs));
            stream.Of<ICommand<float>>().Subscribe(x => Tracer.Get<BrainExercise>().Info("Command: {0}", x));
            stream.Of<ICommand<bool>>().Subscribe(x => Tracer.Get<BrainExercise>().Info("Command: {0}", x));
            stream.Of<ICommand<string>>().Subscribe(x => Tracer.Get<BrainExercise>().Info("Command: {0}", x));
            stream.Of<ICommand<Unit>>().Subscribe(x => Tracer.Get<BrainExercise>().Info("Command: {0}", x));

            var devices = Mock.Of<IDeviceRegistry>();
            var topics = setup.Topics;
            var state = new SystemState();

            // Hook up event stream consumers that perform orthogonal operations.
            new ClockImpulses(Sensorium.Clock.Default).Connect(stream);
            new CommandToBytes().Connect(stream);
            new SensedToImpulse(Sensorium.Clock.Default, topics).Connect(stream);
            new SetSystemState(state).Connect(stream);

            var brain = new Brain(stream, devices, topics, state, Sensorium.Clock.Default);
            var evaluator = CodeEvaluator.Create();
            var anyDeviceType = Guid.NewGuid().ToString();
            var anyDevice = Mock.Of<IDevice>(d => d.Id == Guid.NewGuid().ToString() && d.Type == anyDeviceType);

            // Arrange behaviors
            foreach (var when in setup.Statements)
            {
                brain.Behave(when);
            }

            var tab = "    ";
            // Arrange verifications
            var verifications = SetupVerifications(setup, stream, evaluator, tab);

            // Act by issuing messages.
            SendGivenMessages(setup, stream, anyDeviceType, anyDevice);

            // Assert verifications succeeded.
            verifications.ForEach(v => Assert.True(v.Succeeded, "Verification failed for: " + v.Expression));
        }
Beispiel #3
0
        private static void SendGivenMessages(Setup setup, EventStream stream, string anyDeviceType, IDevice anyDevice)
        {
            foreach (var given in setup.Given)
            {
                var type = setup.Topics.Find(given.Topic);
                Assert.True(type != TopicType.Unknown, "Undefined given topic " + given.Topic);
                ISensed impulse = null;
                // Special [bytes] format
                if (type == TopicType.Void)
                    impulse = new Sensed(given.Topic, new byte[0]);
                else if (given.Value.StartsWith("[") && given.Value.EndsWith("]"))
                    impulse = new Sensed(given.Topic,
                        ParseHex(given.Value.Substring(1, given.Value.Length - 1).Replace(" ", "")));
                else
                {
                    switch (type)
                    {
                        case TopicType.Boolean:
                            impulse = new Sensed(given.Topic, Payload.ToBytes(bool.Parse(given.Value)));
                            break;
                        case TopicType.Number:
                            impulse = new Sensed(given.Topic, Payload.ToBytes(float.Parse(given.Value)));
                            break;
                        case TopicType.String:
                            impulse = new Sensed(given.Topic, Payload.ToBytes(given.Value));
                            break;
                    }
                }

                if (string.IsNullOrEmpty(given.Devices))
                {
                    var usedGiven = setup.ParsedStatements.SelectMany(s => s.When
                        .Where(w => w.Topic == given.Topic && !string.IsNullOrEmpty(w.Devices))
                        .Select(w => w));
                    Assert.False(usedGiven.Any(), string.Format("Invalid configuration. Cannot set given impulse {0} to be emitted with no specific Device Id because impulses of the same topic are expected to be issued with device ids {1}.",
                        given.ToString(),
                        string.Join(", ", usedGiven.Select(w => w.Devices.ToString()))));

                    stream.Push(anyDevice, impulse);
                }
                else
                {
                    // Must issue one impulse for each of the given originating devices.
                    given.Devices
                        .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(id => id.Trim())
                        .Where(id => !string.IsNullOrEmpty(id))
                        .ToList()
                        .ForEach(id => stream.Push(
                            Mock.Of<IDevice>(d => d.Id == id && d.Type == anyDeviceType),
                            impulse));
                }
            }
        }