Exemplo n.º 1
0
        public void Importer_can_send_ImportItem_with_xml_body_in_request_doc()
        {
            // Arrange
            var dekiApiUri     = new XUri("http://mock/@api/deki");
            var importManifest = new XDoc("manifest");
            var item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            var importResponse = new XDoc("requests");
            var mock           = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse));
            mock.Expect().Verb("POST").Uri(item1Uri).RequestDocument(new XDoc("item1").Elem("foo", "bar"));

            // Act
            Importer importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, 0, new Result <Importer>()).Wait();
            var      item1    = new ImportItem(
                "abc",
                new XDoc("request")
                .Attr("method", "POST")
                .Attr("dataid", "abc")
                .Attr("href", item1Uri)
                .Start("body")
                .Attr("type", "xml")
                .Start("item1").Elem("foo", "bar").End()
                .End(),
                new XDoc("manifest"),
                null,
                0);

            importer.WriteDataAsync(item1, new Result()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)));
        }
Exemplo n.º 2
0
        public void ImportManager_only_tries_to_read_from_package_when_there_is_a_dataid()
        {
            var dekiApiUri     = new XUri("http://mock/@api/deki");
            var importManifest = new XDoc("manifest");
            var item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            var importResponse = new XDoc("requests")
                                 .Start("request")
                                 .Attr("method", "GET")
                                 .Attr("href", item1Uri)
                                 .End();
            var mock = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse));
            mock.Expect().Verb("GET").Uri(item1Uri);
            var mockPackageReader = new Mock <IPackageReader>();

            mockPackageReader.Setup(x => x.ReadManifest(It.IsAny <Result <XDoc> >())).Returns(() => importManifest.AsResult());

            // Act
            var manager = ImportManager.CreateAsync(Plug.New(dekiApiUri), 0, mockPackageReader.Object, new Result <ImportManager>()).Wait();

            manager.ImportAsync(new Result()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)), mock.VerificationFailure);
            mockPackageReader.Verify(x => x.ReadManifest(It.IsAny <Result <XDoc> >()), Times.Once());
            mockPackageReader.Verify(x => x.ReadData(It.IsAny <ImportItem>(), It.IsAny <Result <ImportItem> >()), Times.Never());
        }
Exemplo n.º 3
0
 public void Incoming_uri_does_not_get_memorized_all_by_itself()
 {
     SetupService(true);
     _service.AtLocalHost.With(DreamInParam.URI, "http://somehost").With("call", _external.At("externalCallback").ToString()).At("external").Get();
     Assert.AreEqual(new[] { "external" }, _calledPaths.ToArray(), "the wrong paths were called on the mock service");
     Assert.AreEqual(2, _externalCalled, "external endpoint was not called the expected number of time");
 }
Exemplo n.º 4
0
        public void ExportManager_chains_exporter_to_packager()
        {
            // Arrange
            XUri dekiApiUri     = new XUri("http://mock/@api/deki");
            XDoc exportDocument = new XDoc("export");
            XUri item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            XDoc item1Doc       = new XDoc("item1");
            XUri item2Uri       = dekiApiUri.At("foo", "bar", "def");
            XDoc item2Doc       = new XDoc("item2");
            XDoc exportResponse = new XDoc("export")
                                  .Start("requests")
                                  .Start("request")
                                  .Attr("method", "GET")
                                  .Attr("dataid", "abc")
                                  .Attr("href", item1Uri)
                                  .Start("header").Attr("name", "h_1").Attr("value", "v_1").End()
                                  .Start("header").Attr("name", "h_2").Attr("value", "v_2").End()
                                  .End()
                                  .Start("request")
                                  .Attr("method", "GET")
                                  .Attr("dataid", "def")
                                  .Attr("href", item2Uri)
                                  .End()
                                  .End()
                                  .Start("manifest")
                                  .Start("foo").Attr("dataid", "abc").End()
                                  .Start("bar").Attr("dataid", "def").End()
                                  .End();
            AutoMockPlug mock = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "export").With("relto", "0")).RequestDocument(exportDocument).Response(DreamMessage.Ok(exportResponse));
            mock.Expect().Verb("GET").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").Response(DreamMessage.Ok(item1Doc));
            mock.Expect().Verb("GET").Uri(item2Uri).Response(DreamMessage.Ok(item2Doc));
            var writes            = new List <string>();
            var mockPackageWriter = new Mock <IPackageWriter>();

            mockPackageWriter.Setup(x => x.WriteDataAsync(It.IsAny <ExportItem>(), It.IsAny <Result>()))
            .Returns(() => new Result().WithReturn())
            .Callback((ExportItem item, Result result) => writes.Add(item.DataId))
            .AtMost(2)
            .Verifiable();
            mockPackageWriter.Setup(x => x.WriteManifest(It.IsAny <XDoc>(), It.IsAny <Result>()))
            .Returns(() => new Result().WithReturn())
            .AtMostOnce()
            .Verifiable();

            // Act
            ExportManager manager = ExportManager.CreateAsync(Plug.New(dekiApiUri), exportDocument, 0, mockPackageWriter.Object, new Result <ExportManager>()).Wait();

            manager.ExportAsync(new Result()).Wait();

            // Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)), mock.VerificationFailure);
            Assert.AreEqual(2, manager.TotalItems);
            Assert.AreEqual(2, manager.CompletedItems);
            Assert.AreEqual(new[] { "abc", "def" }, writes.ToArray());
            mockPackageWriter.Verify(x => x.Dispose(), Times.Once());
            mockPackageWriter.VerifyAll();
        }
Exemplo n.º 5
0
        public void ImportManager_chains_reader_to_importer()
        {
            // Arrange
            var dekiApiUri     = new XUri("http://mock/@api/deki");
            var importManifest = new XDoc("manifest");
            var item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            var item1Doc       = new XDoc("item1");
            var item2Uri       = dekiApiUri.At("foo", "bar", "def");
            var item2Doc       = new XDoc("item2");
            var importResponse = new XDoc("requests")
                                 .Start("request")
                                 .Attr("method", "POST")
                                 .Attr("dataid", "abc")
                                 .Attr("href", item1Uri)
                                 .Start("header").Attr("name", "h_1").Attr("value", "v_1").End()
                                 .Start("header").Attr("name", "h_2").Attr("value", "v_2").End()
                                 .End()
                                 .Start("request")
                                 .Attr("method", "PUT")
                                 .Attr("dataid", "def")
                                 .Attr("href", item2Uri)
                                 .End();
            var mock = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse));
            mock.Expect().Verb("POST").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").RequestDocument(item1Doc);
            mock.Expect().Verb("PUT").Uri(item2Uri).RequestDocument(item2Doc);

            var mockPackageReader = new Mock <IPackageReader>();

            mockPackageReader.Setup(x => x.ReadManifest(It.IsAny <Result <XDoc> >())).Returns(importManifest.AsResult()).Verifiable("didn't get manifest");
            var item1stream = new MemoryStream(item1Doc.ToBytes());

            mockPackageReader.Setup(x => x.ReadData(It.Is <ImportItem>(y => y.DataId == "abc"), It.IsAny <Result <ImportItem> >()))
            .Returns(() => new ImportItem("abc", importResponse["request[@dataid='abc']"], null, item1stream, item1stream.Length).AsResult())
            .Verifiable();
            var item2stream = new MemoryStream(item2Doc.ToBytes());

            mockPackageReader.Setup(x => x.ReadData(It.Is <ImportItem>(y => y.DataId == "def"), It.IsAny <Result <ImportItem> >()))
            .Returns(() => new ImportItem("def", importResponse["request[@dataid='def']"], null, item2stream, item2stream.Length).AsResult())
            .Verifiable();
            mockPackageReader.Setup(x => x.Dispose()).Verifiable();

            // Act
            var manager = ImportManager.CreateAsync(Plug.New(dekiApiUri), 0, mockPackageReader.Object, new Result <ImportManager>()).Wait();

            manager.ImportAsync(new Result()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)), mock.VerificationFailure);
            mockPackageReader.VerifyAll();
        }
Exemplo n.º 6
0
        private XUri BuildLogHref(string sortedTerms, DateTime since, DateTime before)
        {
            var href = _apiUri.At("site", "query", "log", "=" + XUri.EncodeSegment(sortedTerms))
                       .With("since", DbUtils.ToString(since))
                       .With("before", DbUtils.ToString(before));

            return(href);
        }
Exemplo n.º 7
0
        public void Exporter_can_retrieve_items_by_dataid()
        {
            // Arrange
            XUri dekiApiUri     = new XUri("http://mock/@api/deki");
            XDoc exportDocument = new XDoc("export");
            XUri item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            XDoc item1Doc       = new XDoc("item1");
            XUri item2Uri       = dekiApiUri.At("foo", "bar", "def");
            XDoc item2Doc       = new XDoc("item2");
            XDoc exportResponse = new XDoc("export")
                                  .Start("requests")
                                  .Start("request")
                                  .Attr("method", "GET")
                                  .Attr("dataid", "abc")
                                  .Attr("href", item1Uri)
                                  .Start("header").Attr("name", "h_1").Attr("value", "v_1").End()
                                  .Start("header").Attr("name", "h_2").Attr("value", "v_2").End()
                                  .End()
                                  .Start("request")
                                  .Attr("method", "GET")
                                  .Attr("dataid", "def")
                                  .Attr("href", item2Uri)
                                  .End()
                                  .End()
                                  .Start("manifest")
                                  .Start("foo").Attr("dataid", "abc").End()
                                  .Start("bar").Attr("dataid", "def").End()
                                  .End();
            AutoMockPlug mock = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "export").With("relto", "0")).RequestDocument(exportDocument).Response(DreamMessage.Ok(exportResponse));
            mock.Expect().Verb("GET").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").Response(DreamMessage.Ok(item1Doc));
            mock.Expect().Verb("GET").Uri(item2Uri).Response(DreamMessage.Ok(item2Doc));

            // Act
            Exporter   exporter = Exporter.CreateAsync(Plug.New(dekiApiUri), exportDocument, 0, new Result <Exporter>()).Wait();
            ExportItem item1    = exporter.GetItemAsync("abc", new Result <ExportItem>()).Wait();
            ExportItem item2    = exporter.GetItemAsync("def", new Result <ExportItem>()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)));
            Assert.AreEqual(exportResponse["manifest"], exporter.Manifest);
            Assert.AreEqual(new string[] { "abc", "def" }, exporter.DataIds);
            Assert.AreEqual(exporter.Manifest["*[@dataid='abc']"], item1.ItemManifest);
            Assert.AreEqual(exporter.Manifest["*[@dataid='def']"], item2.ItemManifest);
            Assert.AreEqual(item1Doc, XDocFactory.From(new StreamReader(item1.Data), MimeType.TEXT_XML));
            Assert.AreEqual(item2Doc, XDocFactory.From(new StreamReader(item2.Data), MimeType.TEXT_XML));
        }
Exemplo n.º 8
0
        //--- Methods ---
        private XDoc BuildBugLink(RemoteIssue bug, XDoc doc)
        {
            RemoteStatus status = null;

            if (!string.IsNullOrEmpty(bug.status))
            {
                _statuses.TryGetValue(bug.status, out status);
            }

            bool strikeThrough = status != null && Array.Exists <string>(STRIKE_THROUGH_STATUSES, delegate(string s) {
                return(StringUtil.EqualsInvariantIgnoreCase(status.name.ToLowerInvariant(), s));
            });

            string title = string.Format("{0} (Reporter: {1} Assigned To: {2})",
                                         bug.summary,
                                         bug.reporter,
                                         bug.assignee);

            doc.Start("a").Attr("href", _uri.At("browse").At(bug.key)).Attr("title", title);
            if (strikeThrough)
            {
                doc.Start("del").Value(bug.key).End();
            }
            else
            {
                doc.Value(bug.key);
            }
            doc.End();
            return(doc);
        }
Exemplo n.º 9
0
        protected override Yield Start(XDoc config, Result result)
        {
            yield return(Coroutine.Invoke(base.Start, config, new Result()));

            // read configuration settings
            _username = config["username"].AsText;
            if (string.IsNullOrEmpty(_username))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "username");
            }
            _password = config["password"].AsText;
            if (string.IsNullOrEmpty(_password))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "password");
            }
            _uri = config["jira-uri"].AsUri;
            if (_uri == null)
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "jira-uri");
            }

            _jiraTokenDuration = TimeSpan.FromMinutes(config["jira-session-timeout-mins"].AsInt ?? DEFAULT_LOGIN_TTL);

            // initialize web-service
            _jira     = new JiraSoapServiceService();
            _jira.Url = _uri.At("rpc", "soap", "jirasoapservice-v2").ToString();
            result.Return();
        }
Exemplo n.º 10
0
        protected override Yield Start(XDoc config, Result result)
        {
            yield return(Coroutine.Invoke(base.Start, config, new Result()));

            // read configuration settings
            _username = config["username"].AsText;
            if (string.IsNullOrEmpty(_username))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "username");
            }
            _password = config["password"].AsText;
            if (string.IsNullOrEmpty(_password))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "password");
            }
            _uri = config["mantis-uri"].AsUri;
            if (_uri == null)
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "mantis-uri");
            }

            // initialize web-service
            _service     = new MantisWebServices.MantisConnect();
            _service.Url = _uri.At("api", "soap", "mantisconnect.php").ToString();
            result.Return();
        }
Exemplo n.º 11
0
        protected override Yield Start(XDoc config, Result result)
        {
            yield return(Coroutine.Invoke(base.Start, config, new Result()));

            // read configuration settings
            _username = config["username"].AsText;
            if (string.IsNullOrEmpty(_username))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "username");
            }
            _password = config["password"].AsText;
            if (string.IsNullOrEmpty(_password))
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "password");
            }
            _uri = config["trac-uri"].AsUri;
            if (_uri == null)
            {
                throw new ArgumentException(MISSING_FIELD_ERROR, "trac-uri");
            }

            // initialize web-service
            _trac     = XmlRpcProxyGen.Create <Trac>();
            _trac.Url = _uri.At("login", "xmlrpc").ToString();
            if (!string.IsNullOrEmpty(_username))
            {
                _trac.Credentials = new System.Net.NetworkCredential(_username, _password);
            }

            result.Return();
        }
Exemplo n.º 12
0
        public void Exporter_hits_export_feature_on_creation_using_reltopath()
        {
            // Arrange
            XUri dekiApiUri     = new XUri("http://mock/@api/deki");
            XDoc exportDocument = new XDoc("export")
                                  .Start("page")
                                  .Attr("path", "/")
                                  .Attr("recursive", "true")
                                  .Attr("exclude", "all")
                                  .End();
            XDoc exportResponse = new XDoc("export")
                                  .Start("requests")
                                  .End()
                                  .Start("manifest")
                                  .Elem("justanode")
                                  .End();
            AutoMockPlug mock = MockPlug.Register(dekiApiUri);

            mock.Expect("POST", dekiApiUri.At("site", "export").With("reltopath", "/foo/bar"), exportDocument, DreamMessage.Ok(exportResponse));

            // Act
            Exporter exporter = Exporter.CreateAsync(Plug.New(dekiApiUri), exportDocument, "/foo/bar", new Result <Exporter>()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)));
            Assert.AreEqual(exportResponse["manifest"], exporter.Manifest);
        }
Exemplo n.º 13
0
        public Hashtable PopularPages(
            [DekiExtParam("max results (default: 10)", true)] int?max,
            [DekiExtParam("poll interval (only for js format, default: 30)", true)] int?interval
            )
        {
            int               maxResults  = max ?? 10;
            int               resultCount = 0;
            DekiScriptMap     env         = DreamContext.Current.GetState <DekiScriptMap>();
            DekiScriptLiteral uriLiteral  = env.GetAt("site.uri");
            XUri              deki        = new XUri(uriLiteral.NativeValue.ToString()).At("@api", "deki");
            Hashtable         map         = new Hashtable(StringComparer.OrdinalIgnoreCase);

            map.Add("interval", _ttl.TotalSeconds);
            ArrayList pages = new ArrayList();

            map.Add("pages", pages);
            int total = 0;
            Dictionary <uint, int> rankLookup = new Dictionary <uint, int>();

            lock (_pageViews) {
                foreach (View view in _pageViews)
                {
                    if (rankLookup.ContainsKey(view.PageId))
                    {
                        rankLookup[view.PageId]++;
                    }
                    else
                    {
                        rankLookup[view.PageId] = 1;
                    }
                    total++;
                }
            }
            List <Tuplet <uint, int> > rank = new List <Tuplet <uint, int> >();

            foreach (KeyValuePair <uint, int> kvp in rankLookup)
            {
                rank.Add(new Tuplet <uint, int>(kvp.Key, kvp.Value));
            }
            rank.Sort(delegate(Tuplet <uint, int> a, Tuplet <uint, int> b) {
                return(b.Item2.CompareTo(a.Item2));
            });
            map.Add("total", total);
            foreach (Tuplet <uint, int> page in rank)
            {
                Hashtable pageMap = new Hashtable(StringComparer.OrdinalIgnoreCase);
                pages.Add(pageMap);

                // BUGBUGBUG (arnec): the AsLocalUri should not be required after bug #5964 is resolved
                pageMap.Add("page", DekiScriptExpression.Constant(deki.At("$page").AsLocalUri(), new[] { DekiScriptExpression.Constant(page.Item1), DekiScriptExpression.Constant(true) }));
                pageMap.Add("views", page.Item2);
                resultCount++;
                if (resultCount >= maxResults)
                {
                    break;
                }
            }
            return(map);
        }
Exemplo n.º 14
0
 public XUri PropertyUri(XUri parentUri)
 {
     if (ResourceType != Type.PROPERTY)
     {
         throw new InvalidOperationException("invalid operation for resource type");
     }
     return(parentUri.At("properties", XUri.DoubleEncodeSegment(Name)));
 }
Exemplo n.º 15
0
        public void Importer_Items_are_populated_with_request_and_manifest_docs()
        {
            // Arrange
            var dekiApiUri     = new XUri("http://mock/@api/deki");
            var importManifest = new XDoc("manifest")
                                 .Start("item").Attr("dataid", "abc").Elem("foo", "bar").End()
                                 .Start("item").Attr("dataid", "def").Elem("baz", "flip").End();
            var item1Uri       = dekiApiUri.At("foo", "bar", "abc");
            var item2Uri       = dekiApiUri.At("foo", "bar", "def");
            var importResponse = new XDoc("requests")
                                 .Start("request")
                                 .Attr("method", "POST")
                                 .Attr("dataid", "abc")
                                 .Attr("href", item1Uri)
                                 .Start("header").Attr("name", "h_1").Attr("value", "v_1").End()
                                 .Start("header").Attr("name", "h_2").Attr("value", "v_2").End()
                                 .End()
                                 .Start("request")
                                 .Attr("method", "PUT")
                                 .Attr("dataid", "def")
                                 .Attr("href", item2Uri)
                                 .End();
            var mock = MockPlug.Register(dekiApiUri);

            mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse));

            // Act
            var importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, 0, new Result <Importer>()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)));
            var item1 = importer.Items.Where(x => x.DataId == "abc").FirstOrDefault();

            Assert.IsNotNull(item1);
            Assert.IsNotNull(item1.Manifest);
            Assert.AreEqual(importManifest[".//*[@dataid='abc']"], item1.Manifest);
            Assert.IsNotNull(item1.Request);
            Assert.AreEqual(importResponse[".//*[@dataid='abc']"], item1.Request);
            var item2 = importer.Items.Where(x => x.DataId == "def").FirstOrDefault();

            Assert.IsNotNull(item2);
            Assert.IsNotNull(item2.Manifest);
            Assert.AreEqual(importManifest[".//*[@dataid='def']"], item2.Manifest);
            Assert.IsNotNull(item1.Request);
            Assert.AreEqual(importResponse[".//*[@dataid='def']"], item2.Request);
        }
 public static string UriAppendPath(
     [DekiScriptParam("base uri")] XUri uri,
     [DekiScriptParam("path segments to append (must a string or list of strings)", true)] object path
     )
 {
     if (path is string)
     {
         uri = uri.At((string)path);
     }
     else if (path is ArrayList)
     {
         foreach (string segment in (ArrayList)path)
         {
             uri = uri.At(segment);
         }
     }
     return(uri.ToString());
 }
Exemplo n.º 17
0
 public IMockInvokeExpectationParameter At(string[] path)
 {
     if (_expectedUri == null)
     {
         _expectedUri = _baseUri;
     }
     _expectedUri = _expectedUri.At(path);
     return(this);
 }
Exemplo n.º 18
0
        //--- Methods ---

        /// <summary>
        /// Application specific base uri for a given request
        /// </summary>
        /// <param name="request">HttpRequest instance.</param>
        /// <returns>Base Uri.</returns>
        public XUri GetRequestBaseUri(HttpRequest request)
        {
            var transport = new XUri(request.Url).WithoutPathQueryFragment().AtAbsolutePath(request.ApplicationPath);
            var prefix    = _appConfig.Prefix;

            if (!string.IsNullOrEmpty(prefix))
            {
                transport = transport.At(prefix);
            }
            return(transport);
        }
Exemplo n.º 19
0
        private XDoc GetPropertyXml(IList <ResourceBE> properties, XUri parentResourceUri, bool collection, string propSuffix, bool?explicitRevisionInfo, uint?contentCutoff, XDoc doc)
        {
            bool requiresEnd = false;

            if (collection)
            {
                string rootPropertiesNode = string.IsNullOrEmpty(propSuffix) ? "properties" : "properties." + propSuffix;
                if (doc == null)
                {
                    doc = new XDoc(rootPropertiesNode);
                }
                else
                {
                    doc.Start(rootPropertiesNode);
                    requiresEnd = true;
                }

                doc.Attr("count", properties.Count);

                if (parentResourceUri != null)
                {
                    //Note: this assumes that the property collection of a resource is always accessed by appending "properties" to the parent URI
                    doc.Attr("href", parentResourceUri.At("properties"));
                }
            }
            else
            {
                doc = XDoc.Empty;
            }

            //Batch retrieve users for user.modified and user.deleted
            Dictionary <uint, UserBE> usersById = new Dictionary <uint, UserBE>();

            foreach (ResourceBE r in properties)
            {
                usersById[r.UserId] = null;
            }
            if (!ArrayUtil.IsNullOrEmpty(properties))
            {
                usersById = DbUtils.CurrentSession.Users_GetByIds(usersById.Keys.ToArray()).AsHash(e => e.ID);
            }

            foreach (ResourceBE p in properties)
            {
                doc = AppendPropertyXml(doc, p, parentResourceUri, propSuffix, explicitRevisionInfo, contentCutoff, usersById);
            }

            if (requiresEnd)
            {
                doc.End();
            }

            return(doc);
        }
Exemplo n.º 20
0
            //--- Class Methods ---
            internal static AMedia New(XUri uri, XDoc config)
            {
                // check if the uri is a viddler video
                if (uri.Scheme.EqualsInvariantIgnoreCase("kaltura"))
                {
                    if (uri.Segments.Length >= 1)
                    {
                        string entryID   = uri.Segments[0];
                        string partnerID = config["kaltura/partner-id"].AsText;

                        // check if extension is configured for kaltura integration
                        if (!string.IsNullOrEmpty(partnerID))
                        {
                            bool remix = !(uri.GetParam("edit", null) ?? uri.GetParam("remix", "no")).EqualsInvariantIgnoreCase("no");

                            // verify that user has permission to remix content on current page
                            if (remix)
                            {
                                Plug dekiApi = GetDekiApi(config);
                                if (dekiApi != null)
                                {
                                    try {
                                        DekiScriptMap env    = DreamContext.Current.GetState <DekiScriptMap>();
                                        string        pageid = env.GetAt("page.id").AsString();
                                        string        userid = env.GetAt("user.id").AsString();
                                        XDoc          users  = dekiApi.At("pages", pageid, "allowed").With("permissions", "UPDATE").Post(new XDoc("users").Start("user").Attr("id", userid).End()).ToDocument();
                                        remix = !users[string.Format(".//user[@id='{0}']", userid)].IsEmpty;
                                    } catch (Exception e) {
                                        _log.Error("unable to verify user permission on page", e);
                                    }
                                }
                            }

                            // check if SEO links are explicitly disabled
                            bool seo = !(config["kaltura/seo-links"].AsText ?? "enabled").EqualsInvariantIgnoreCase("disabled");

                            // determin which UI configuration to use based on user's permissions and embed settings for video
                            string uiConfID = remix ? config["kaltura/uiconf/player-mix"].AsText : config["kaltura/uiconf/player-nomix"].AsText;
                            if (!string.IsNullOrEmpty(uiConfID))
                            {
                                uri = config["kaltura/server-uri"].AsUri ?? new XUri("http://www.kaltura.com");
                                uri = uri.At("index.php", "kwidget", "wid", "_" + partnerID, "uiconf_id", uiConfID, "entry_id", entryID);
                                return(new KalturaVideo(uri, remix, seo));
                            }
                        }
                    }
                }
                return(null);
            }
Exemplo n.º 21
0
        //--- Methods ---
        private XDoc BuildBugLink(IssueData issue, XDoc doc)
        {
            bool strikeThrough = issue.status != null && Array.Exists <string>(STRIKE_THROUGH_STATUSES, delegate(string s) {
                return(StringUtil.EqualsInvariantIgnoreCase(issue.status.name, s));
            });

            string title = string.Format("{0} (Reporter: {1} AssignedTo: {2})",
                                         issue.summary,
                                         issue.reporter != null ? issue.reporter.name : string.Empty,
                                         issue.handler != null ? issue.handler.name : string.Empty);


            doc.Start("a").Attr("href", _uri.At("view.php").With("id", issue.id)).Attr("title", title);
            if (strikeThrough)
            {
                doc.Start("del").Value("#" + issue.id).End();
            }
            else
            {
                doc.Value("#" + issue.id);
            }
            doc.End();
            return(doc);
        }
Exemplo n.º 22
0
        public XUri GetUriContent(ResourceBE file, bool?includeRevision)
        {
            if (includeRevision == null)
            {
                includeRevision = !file.IsHeadRevision();
            }

            XUri uri = GetUri(file);

            if (includeRevision.Value)
            {
                uri = uri.With("revision", file.Revision.ToString());
            }

            uri = uri.At(Title.AsApiParam(file.Name));
            return(uri);
        }
Exemplo n.º 23
0
 private void AttachmentChanged(DateTime eventTime, ResourceBE attachment, params string[] path)
 {
     try {
         XUri     channel       = _channel.At(FILES).At(path);
         XUri     attachmentUri = AttachmentBL.Instance.GetUri(attachment);
         XUri     resource      = attachmentUri.WithHost(_wikiid);
         string[] origin        = new string[] { attachmentUri.AsServerUri().ToString() };
         Queue(eventTime, channel, resource, origin, new XDoc("deki-event")
               .Elem("channel", channel)
               .Elem("fileid", attachment.MetaXml.FileId ?? 0)
               .Elem("uri", attachmentUri.AsServerUri().ToString())
               .Elem("content.uri", attachmentUri.AsServerUri().ToString())
               .Elem("revision.uri", attachmentUri.At("info").With("revision", attachment.Revision.ToString()).AsServerUri().ToString())
               .Elem("path", attachmentUri.Path));
     } catch (Exception e) {
         _log.WarnExceptionMethodCall(e, "AttachmentChanged", "event couldn't be created");
     }
 }
        public static string UriBuild(
            [DekiScriptParam("base uri")] XUri uri,
            [DekiScriptParam("path segments to append (must a string or list of strings)", true)] object path,
            [DekiScriptParam("query parameters to append", true)] Hashtable args
            )
        {
            if (path is string)
            {
                uri = uri.AtPath((string)path);
            }
            else if (path is ArrayList)
            {
                foreach (string segment in (ArrayList)path)
                {
                    uri = uri.At(XUri.EncodeSegment(segment));
                }
            }
            if (args != null)
            {
                foreach (DictionaryEntry entry in args)
                {
                    string key = (string)entry.Key;

                    // remove existing parameter
                    uri = uri.WithoutParams(key);

                    // check if entry is a list of values
                    if (entry.Value is ArrayList)
                    {
                        foreach (var value in (ArrayList)entry.Value)
                        {
                            uri = uri.With(key, SysUtil.ChangeType <string>(value));
                        }
                    }
                    else if (entry.Value != null)
                    {
                        uri = uri.With(key, SysUtil.ChangeType <string>(entry.Value));
                    }
                }
            }
            return(uri.ToString());
        }
Exemplo n.º 25
0
        public void Importer_hits_import_feature_with_reltopath()
        {
            // Arrange
            XUri dekiApiUri     = new XUri("http://mock/@api/deki");
            XDoc importManifest = new XDoc("manifest");
            XDoc importResponse = new XDoc("requests")
                                  .Start("request").Attr("dataid", "a").End()
                                  .Start("request").Attr("dataid", "b").End()
                                  .Start("request").Attr("dataid", "c").End();
            AutoMockPlug mock = MockPlug.Register(dekiApiUri);

            mock.Expect("POST", dekiApiUri.At("site", "import").With("reltopath", "/foo/bar"), importManifest, DreamMessage.Ok(importResponse));

            // Act
            Importer importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, "/foo/bar", new Result <Importer>()).Wait();

            //Assert
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)));
            Assert.AreEqual(importManifest, importer.Manifest);
            Assert.AreEqual(new[] { "a", "b", "c" }, importer.Items.Select(x => x.DataId).ToArray());
        }
Exemplo n.º 26
0
 //--- Methods ---
 public void InstanceStarted(DateTime eventTime)
 {
     try {
         XUri channel  = _channel.At(SITE, STARTED);
         XUri resource = _apiUri.AsServerUri();
         Queue(eventTime, channel, resource, new[] { _apiUri.AsServerUri().ToString() }, new XDoc("deki-event")
               .Elem("channel", channel)
               .Elem("uri", _apiUri.AsServerUri().ToString()));
     } catch (Exception e) {
         _log.WarnExceptionMethodCall(e, "InstanceStarted", "event couldn't be created");
     }
 }
Exemplo n.º 27
0
        public void Dispatch_based_on_recipients()
        {
            var proxyRecipient1 = "mailto:///[email protected]";
            var proxyRecipient2 = "mailto:///[email protected]";
            var msg = new XDoc("foo");
            var ev = new DispatcherEvent(
                    msg,
                    new XUri("channel:///foo/bar"),
                    new XUri("http://foobar.com/some/page")
                )
                .WithRecipient(false,
                    new DispatcherRecipient(new XUri(proxyRecipient1)),
                    new DispatcherRecipient(new XUri("mailto:///[email protected]")),
                    new DispatcherRecipient(new XUri(proxyRecipient2)
                )
            );
            var dispatches = new Dictionary<XUri, DreamMessage>();
            var testUri = new XUri("http:///").At(StringUtil.CreateAlphaNumericKey(4));
            var dispatchHappened = new AutoResetEvent(false);
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                dispatches.Add(plug.Uri, request);
                dispatchHappened.Set();
                response.Return(DreamMessage.Ok());
            });
            var combinedSetUpdated = new AutoResetEvent(false);
            _dispatcher.CombinedSetUpdated += delegate {
                _log.DebugFormat("set updated");
                combinedSetUpdated.Set();
            };

            var proxy = testUri.At("proxy");
            _log.DebugFormat("registering set");
            _dispatcher.RegisterSet(
                "abc",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "channel:///foo/*")
                        .Elem("uri.proxy", proxy)
                        .Start("recipient").Elem("uri", proxyRecipient1).End()
                        .Start("recipient").Elem("uri", proxyRecipient2).End()
                    .End()
                    .Start("subscription")
                        .Attr("id", "2")
                        .Elem("channel", "channel:///foo/*")
                        .Start("recipient").Elem("uri", testUri.At("sub2")).End()
                    .End(),
                "def"
            );

            //Set updates happen asynchronously, so give it a chance
            _log.DebugFormat("giving registration a chance to manifest");
            Assert.IsTrue(combinedSetUpdated.WaitOne(10000, false));
            _log.DebugFormat("dispatching event");
            _dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(dispatchHappened.WaitOne(1000, false));
            Thread.Sleep(200);
            Assert.AreEqual(1, dispatches.Count);
            Assert.IsTrue(dispatches.ContainsKey(proxy));
            Assert.AreEqual(msg, dispatches[proxy].ToDocument());
            Assert.AreEqual(ev.Id, dispatches[proxy].Headers.DreamEventId);
            string[] recipients = dispatches[proxy].Headers.DreamEventRecipients;
            Assert.AreEqual(2, recipients.Length);
            Assert.Contains(proxyRecipient1, recipients);
            Assert.Contains(proxyRecipient2, recipients);
        }
Exemplo n.º 28
0
 public void TestAppendPath5()
 {
     XUri uri = new XUri("http://www.dummy.com:8081/first/second?query=arg");
     uri = uri.At("foo/bar");
 }
Exemplo n.º 29
0
        public void Dispatch_based_on_recipients()
        {
            int workers;
            int io;
            ThreadPool.GetAvailableThreads(out workers, out io);
            _log.DebugFormat("threadpool threads: {0}/{1}", workers, io);
            string proxyRecipient1 = "mailto:///[email protected]";
            string proxyRecipient2 = "mailto:///[email protected]";
            XDoc msg = new XDoc("foo");
            DispatcherEvent ev = new DispatcherEvent(
                msg,
                new XUri("channel:///foo/bar"),
                new XUri("http://foobar.com/some/page"))
                .WithRecipient(false,
                    new DispatcherRecipient(new XUri(proxyRecipient1)),
                    new DispatcherRecipient(new XUri("mailto:///[email protected]")),
                    new DispatcherRecipient(new XUri(proxyRecipient2)));
            Dictionary<XUri, DreamMessage> dispatches = new Dictionary<XUri, DreamMessage>();
            XUri testUri = new XUri("http:///").At(StringUtil.CreateAlphaNumericKey(4));
            AutoResetEvent resetEvent = new AutoResetEvent(false);
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                dispatches.Add(plug.Uri, request);
                resetEvent.Set();
                response.Return(DreamMessage.Ok());
            });
            Plug owner = Plug.New("mock:///pubsub");
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            Dispatcher dispatcher = new Dispatcher(new DispatcherConfig { ServiceUri = owner, ServiceAccessCookie = cookie });
            AutoResetEvent setResetEvent = new AutoResetEvent(false);
            dispatcher.CombinedSetUpdated += delegate {
                _log.DebugFormat("set updated");
                setResetEvent.Set();
            };

            XUri proxy = testUri.At("proxy");
            _log.DebugFormat("registering set");
            dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "channel:///foo/*")
                        .Elem("uri.proxy", proxy)
                        .Start("recipient").Elem("uri", proxyRecipient1).End()
                        .Start("recipient").Elem("uri", proxyRecipient2).End()
                    .End()
                    .Start("subscription")
                        .Attr("id", "2")
                        .Elem("channel", "channel:///foo/*")
                        .Start("recipient").Elem("uri", testUri.At("sub2")).End()
                    .End());

            //Set updates happen asynchronously, so give it a chance
            _log.DebugFormat("giving registration a chance to manifest");
            Assert.IsTrue(setResetEvent.WaitOne(10000, false));
            _log.DebugFormat("dispatching event");
            dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(resetEvent.WaitOne(1000, false));
            Thread.Sleep(200);
            Assert.AreEqual(1, dispatches.Count);
            Assert.IsTrue(dispatches.ContainsKey(proxy));
            Assert.AreEqual(msg, dispatches[proxy].ToDocument());
            Assert.AreEqual(ev.Id, dispatches[proxy].Headers.DreamEventId);
            string[] recipients = dispatches[proxy].Headers.DreamEventRecipients;
            Assert.AreEqual(2, recipients.Length);
            Assert.Contains(proxyRecipient1, recipients);
            Assert.Contains(proxyRecipient2, recipients);
            MockPlug.Deregister(testUri);
        }
Exemplo n.º 30
0
        public void Dispatch_based_on_channel_match_with_different_wikiid_patterns_but_same_proxy_destination()
        {
            DispatcherEvent ev = new DispatcherEvent(
                new XDoc("msg"),
                new XUri("event://sales.mindtouch.com/deki/comments/create"),
                new XUri("http://foobar.com/some/comment"));
            List<DreamMessage> dispatches = new List<DreamMessage>();
            XUri testUri = new XUri("http://sales.mindtouch.com/").At(StringUtil.CreateAlphaNumericKey(4));
            AutoResetEvent resetEvent = new AutoResetEvent(false);
            int dispatchCounter = 0;
            int expectedDispatches = 0;
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                if(testUri == plug.Uri) {
                    dispatches.Add(request);
                    dispatchCounter++;
                    // ReSharper disable AccessToModifiedClosure
                    if(dispatchCounter >= expectedDispatches) {
                        // ReSharper restore AccessToModifiedClosure
                        resetEvent.Set();
                    }
                }
                response.Return(DreamMessage.Ok());
            });
            Plug owner = Plug.New("mock:///pubsub");
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            Dispatcher dispatcher = new Dispatcher(new DispatcherConfig { ServiceUri = owner, ServiceAccessCookie = cookie });
            int expectedCombinedSetUpdates = 2;
            int combinedSetUpdates = 0;
            AutoResetEvent setResetEvent = new AutoResetEvent(false);
            dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
                if(combinedSetUpdates >= expectedCombinedSetUpdates) {
                    setResetEvent.Set();
                }
            };
            dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "event://sales.mindtouch.com/deki/comments/create")
                        .Elem("channel", "event://sales.mindtouch.com/deki/comments/update")
                        .Elem("uri.proxy", testUri)
                        .Start("recipient").Elem("uri", testUri.At("sub1")).End()
                    .End());
            dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner2")
                    .Start("subscription")
                        .Attr("id", "3")
                        .Elem("channel", "event://*/deki/comments/create")
                        .Elem("channel", "event://*/deki/comments/update")
                        .Elem("uri.proxy", testUri)
                        .Start("recipient").Elem("uri", testUri.At("sub2")).End()
                    .End());

            // combinedset updates happen asynchronously, so give'em a chance
            Assert.IsTrue(setResetEvent.WaitOne(10000, false));
            expectedDispatches = 1;
            dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Assert.AreEqual(1, dispatches.Count);
            Assert.AreEqual(ev.AsMessage().ToDocument(), dispatches[0].ToDocument());
            Assert.AreEqual(ev.Id, dispatches[0].Headers.DreamEventId);
            MockPlug.Deregister(testUri);
        }
Exemplo n.º 31
0
        public void Dispatch_based_on_channel_and_resource_match()
        {
            DispatcherEvent ev = new DispatcherEvent(
                new XDoc("msg"),
                new XUri("channel:///foo/bar"),
                new XUri("http://foobar.com/some/page"));
            Dictionary<XUri, DreamMessage> dispatches = new Dictionary<XUri, DreamMessage>();
            XUri testUri = new XUri("http:///").At(StringUtil.CreateAlphaNumericKey(4));
            AutoResetEvent resetEvent = new AutoResetEvent(false);
            int expectedDispatches = 0;
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                dispatches.Add(plug.Uri, request);
                // ReSharper disable AccessToModifiedClosure
                if(dispatches.Count >= expectedDispatches) {
                    // ReSharper restore AccessToModifiedClosure
                    resetEvent.Set();
                }
                response.Return(DreamMessage.Ok());
            });
            Plug owner = Plug.New("mock:///pubsub");
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            Dispatcher dispatcher = new Dispatcher(new DispatcherConfig { ServiceUri = owner, ServiceAccessCookie = cookie });
            int expectedCombinedSetUpdates = 2;
            int combinedSetUpdates = 0;
            AutoResetEvent setResetEvent = new AutoResetEvent(false);
            dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
                if(combinedSetUpdates >= expectedCombinedSetUpdates) {
                    setResetEvent.Set();
                }
            };
            dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "channel:///foo/*")
                        .Elem("uri.resource", "http://*/some/*")
                        .Start("recipient").Elem("uri", testUri.At("sub1")).End()
                    .End()
                    .Start("subscription")
                        .Attr("id", "2")
                        .Elem("channel", "channel:///foo/baz")
                        .Elem("uri.resource", "http://*/some/*")
                        .Start("recipient").Elem("uri", testUri.At("sub2")).End()
                    .End());
            dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner2")
                    .Start("subscription")
                        .Attr("id", "3")
                        .Elem("channel", "channel:///foo/bar")
                        .Elem("uri.resource", "http://foobar.com/some/page")
                        .Start("recipient").Elem("uri", testUri.At("sub3")).End()
                    .End()
                    .Start("subscription")
                        .Attr("id", "4")
                        .Elem("channel", "channel:///foo/bar")
                        .Elem("uri.resource", "http://baz.com/some/*")
                        .Start("recipient").Elem("uri", testUri.At("sub4")).End()
                    .End());

            // combinedset updates happen asynchronously, so give'em a chance
            Assert.IsTrue(setResetEvent.WaitOne(10000, false));
            expectedDispatches = 2;
            dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Thread.Sleep(200);
            Assert.AreEqual(2, dispatches.Count);
            Assert.IsTrue(dispatches.ContainsKey(testUri.At("sub1")));
            Assert.AreEqual(ev.AsMessage().ToDocument(), dispatches[testUri.At("sub1")].ToDocument());
            Assert.AreEqual(ev.Id, dispatches[testUri.At("sub1")].Headers.DreamEventId);
            Assert.IsTrue(dispatches.ContainsKey(testUri.At("sub3")));
            MockPlug.Deregister(testUri);
        }
Exemplo n.º 32
0
 public void SubscriptionSet_combination_splits_multichannel_subs()
 {
     XUri owner = new XUri("http:///owner");
     XUri c1 = new XUri("channel:///c1");
     XUri c2 = new XUri("channel:///c2");
     XUri c3 = new XUri("channel:///c3");
     XUri r1 = new XUri("http:///r1");
     PubSubSubscription sub = new PubSubSubscription(
         new XDoc("subscription")
             .Attr("id", "123")
             .Elem("channel", c1)
             .Elem("channel", c2)
             .Elem("channel", c3)
             .Elem("uri.proxy", "http:///proxy")
             .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End()
             .Start("recipient").Attr("auth-token", "def").Elem("uri", "http:///r2").End()
         , null
         );
     DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
     PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(owner, 0, cookie, sub);
     Assert.AreEqual(3, combinedSet.Subscriptions.Length);
     PubSubSubscription subx = combinedSet.Subscriptions[0];
     Assert.AreEqual(owner.At("publish"), subx.Destination);
     Assert.AreEqual(1, subx.Channels.Length);
     Assert.AreEqual(c1, subx.Channels[0]);
     Assert.AreEqual(2, subx.Recipients.Length);
     Assert.AreEqual(r1, subx.Recipients[0].Uri);
     subx = combinedSet.Subscriptions[1];
     Assert.AreEqual(owner.At("publish"), subx.Destination);
     Assert.AreEqual(1, subx.Channels.Length);
     Assert.AreEqual(c2, subx.Channels[0]);
     Assert.AreEqual(2, subx.Recipients.Length);
     Assert.AreEqual(r1, subx.Recipients[0].Uri);
 }
Exemplo n.º 33
0
        public void SubscriptionSet_combination_merges_subs_for_same_channel()
        {
            XUri owner = new XUri("http:///owner");
            XUri c1 = new XUri("channel:///c1");
            XUri c2 = new XUri("channel:///c2");
            XUri c3 = new XUri("channel:///c3");
            XDoc x1 = new XDoc("rule").Value("v1");
            XDoc x2 = new XDoc("rule").Value("v2");
            XDoc x3 = new XDoc("super-custom-filter").Elem("foo", "bar");

            XUri r1 = new XUri("http:///r1");
            XUri r2 = new XUri("http:///r2");
            PubSubSubscription sub1 = new PubSubSubscription(
                new XDoc("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c2)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End()
                , null
                );
            PubSubSubscription sub2 = new PubSubSubscription(
                new XDoc("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c3)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r2).End()
                , null
                );
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(owner, 0, cookie, sub1, sub2);
            Assert.AreEqual(3, combinedSet.Subscriptions.Length);
            foreach(PubSubSubscription subx in combinedSet.Subscriptions) {
                switch(subx.Channels[0].ToString()) {
                case "channel:///c1":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c1, subx.Channels[0]);
                    Assert.AreEqual(2, subx.Recipients.Length);
                    bool foundR1 = false;
                    bool foundR2 = false;
                    foreach(DispatcherRecipient r in subx.Recipients) {
                        if(r.Uri == r1) {
                            foundR1 = true;
                        } else if(r.Uri == r2) {
                            foundR2 = true;
                        }
                    }
                    Assert.IsTrue(foundR1 && foundR2);
                    break;
                case "channel:///c2":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c2, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r1, subx.Recipients[0].Uri);
                    break;
                case "channel:///c3":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c3, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r2, subx.Recipients[0].Uri);
                    break;
                default:
                    Assert.Fail();
                    break;
                }
            }
        }
Exemplo n.º 34
0
        public void Failed_dispatch_followed_by_success_should_reset_fail_count()
        {
            bool fail = true;
            DispatcherEvent ev = new DispatcherEvent(
             new XDoc("msg"),
             new XUri("channel:///foo/bar"),
             new XUri("http://foobar.com/some/page"));
            XUri testUri = new XUri("http:///").At(StringUtil.CreateAlphaNumericKey(4));
            AutoResetEvent resetEvent = new AutoResetEvent(false);
            int mockCalled = 0;
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                mockCalled++;
                // ReSharper disable AccessToModifiedClosure
                _log.DebugFormat("mock called {0} times (fail={1}): {2}", mockCalled, fail, uri);
                // ReSharper restore AccessToModifiedClosure
                resetEvent.Set();
                // ReSharper disable AccessToModifiedClosure
                response.Return(fail ? DreamMessage.InternalError() : DreamMessage.Ok());
                // ReSharper restore AccessToModifiedClosure
            });
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            Dispatcher dispatcher = new Dispatcher(new DispatcherConfig { ServiceUri = Plug.New("mock:///pubsub"), ServiceAccessCookie = cookie });
            int expectedCombinedSetUpdates = 1;
            int combinedSetUpdates = 0;
            AutoResetEvent setResetEvent = new AutoResetEvent(false);
            dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
                if(combinedSetUpdates >= expectedCombinedSetUpdates) {
                    setResetEvent.Set();
                }
            };
            string location = dispatcher.RegisterSet(
                new XDoc("subscription-set")
                    .Attr("max-failures", 1)
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                        .Attr("id", "1")
                        .Elem("channel", "channel:///foo/*")
                        .Start("recipient").Elem("uri", testUri.At("foo")).End()
                    .End()).Item1.Location;
            Assert.IsTrue(setResetEvent.WaitOne(10000, false));
            Assert.IsNotNull(dispatcher[location]);

            _log.DebugFormat("first dispatch (fail={0})", fail);
            dispatcher.Dispatch(ev);
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Thread.Sleep(1000); // failure gets dealt with async
            Assert.IsNotNull(dispatcher[location]);
            fail = false;

            _log.DebugFormat("second dispatch (fail={0})", fail);
            dispatcher.Dispatch(ev);
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Thread.Sleep(1000); // failure reset gets dealt with async
            Assert.IsNotNull(dispatcher[location]);
            fail = true;

            _log.DebugFormat("third dispatch (fail={0})", fail);
            dispatcher.Dispatch(ev);
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Thread.Sleep(1000); // failure gets dealt with async
            Assert.IsNotNull(dispatcher[location]);

            _log.DebugFormat("fourth dispatch (fail={0})", fail);
            dispatcher.Dispatch(ev);
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Thread.Sleep(1000); // failure gets dealt with async
            Assert.IsNull(dispatcher[location]);
            MockPlug.Deregister(testUri);
        }
Exemplo n.º 35
0
        public XDoc ReloadNotification(
            [DekiExtParam("Page id", false)] string id
            )
        {
            string containerId = "pn_" + StringUtil.CreateAlphaNumericKey(4);
            XUri   self        = Self.Uri.AsPublicUri();
            XDoc   doc         = new XDoc("html")
                                 .Start("body").Start("div")
                                 .Attr("id", containerId)
                                 .End().End()
                                 .Start("tail")
                                 .Start("script")
                                 .Attr("type", "text/javascript")
                                 .Value(string.Format("Deki.Api.Poll({0},'{1}','{2}');", _pollInterval.TotalMilliseconds, containerId, self.At("changed", id)))
                                 .End()
                                 .End();

            doc.EndAll();
            return(doc);
        }
Exemplo n.º 36
0
        //--- Constructor ---
        internal DekiInstance(DekiWikiService deki, string id, XDoc instanceConfig, ILicenseController licenseController)
        {
            if (deki == null)
            {
                throw new ArgumentNullException("deki");
            }
            if (string.IsNullOrEmpty(id))
            {
                throw new ArgumentNullException("id");
            }
            this.Id = id;

            // Note (arnec): this is now the the third place we define a wikiid based logger repository, however constructors interdependencies
            // currently neccessitates this duplication, and fortunately it is mostly an aesthetic issue.
            _loggerRepository = new ContextLoggerRepository("[" + Id + "] ");
            _log = _loggerRepository.Get(GetType());
            this.TimerFactory = TaskTimerFactory.Create(this);
            this.Cache        = new DreamCache(TimerFactory);
            var cacheFactory     = new InMemoryKeyValueCacheFactory(TimerFactory);
            var searchSerializer = new SearchSerializer();

            cacheFactory.SetSerializer <SearchResult>(searchSerializer);
            cacheFactory.SetSerializer <SearchResultDetail>(searchSerializer);
            this.SearchCache   = cacheFactory.Create();
            this.Config        = instanceConfig;
            _licenseController = licenseController;
            this.Log           = LogManager.GetLogger(deki.GetType().Name + "_" + id);
            _deki   = deki;
            _status = DekiInstanceStatus.CREATED;
            _apiKey = Config[ConfigBL.SECURITY_APIKEY].AsText;
            foreach (XDoc hostDoc in Config["host"])
            {
                string host = hostDoc.Contents;
                if (!StringUtil.EqualsInvariantIgnoreCase(host, "*"))
                {
                    string port   = hostDoc["@port"].AsText;
                    string scheme = hostDoc["@https"].AsBool.GetValueOrDefault() ? "https://" : "http://";
                    string uri    = scheme + host + (string.IsNullOrEmpty(port) ? "" : ":" + port);
                    _canonicalUri = new XUri(uri);
                    _log.DebugFormat("divined canonical use from hosts as {0}", _canonicalUri);
                    break;
                }
            }
            if (_canonicalUri == null)
            {
                // Note (arnec): this is a best guess fallback. It will only work in these scenarios:
                // a) The host was set up with a uri.public that has ends in @api and with the @api points to the site uri, or
                // b) The api lives on the same machine as the site, so that deriving uri.public for the host from the machine
                // IP happens to point to the same machine
                // Either way it relies on the hard-coded assumption that the api is accessible via {site}/@api
                _canonicalUri = DreamContext.Current.ServerUri;
                if (_canonicalUri.LastSegment.EqualsInvariantIgnoreCase("@api"))
                {
                    _canonicalUri = _canonicalUri.WithoutLastSegment();
                }
                _log.DebugFormat("using server uri as canonical uri: {0}", _canonicalUri);
            }
            else
            {
                // Note (arnec): Propagating a much hard-coded assumption, i.e. that the Api for any Deki instance can be accessed
                // at the instances' canonical uri plus @api

                // register the api uri with the dream host so that requests originating from within Dream are guaranteed to be locally routed
                _deki.Env.At("status", "aliases").Post(new XDoc("aliases").Elem("uri.alias", _canonicalUri.At("@api")), new Result <DreamMessage>());
            }
        }
Exemplo n.º 37
0
        public void PubSub_downstream_chaining_and_subscription_propagation()
        {
            XUri downstreamUri = new XUri("http://localhost/downstream");
            var mock = MockPlug.Register(downstreamUri);
            XDoc downstreamDoc = null;
            mock.Expect().Verb("GET").Uri(downstreamUri).Response(DreamMessage.Ok(new XDoc("subscription-set")
                .Elem("uri.owner", downstreamUri)
                .Start("subscription")
                   .Attr("id", "1")
                   .Elem("channel", "channel:///foo/*")
                   .Elem("uri.proxy", downstreamUri.At("publish"))
                   .Start("recipient").Elem("uri", "http:///foo/sub1").End()
                .End()));
            mock.Expect().Verb("POST").Uri(downstreamUri).RequestDocument(doc => {
                downstreamDoc = doc;
                return true;
            });

            // create service, which should subscribe to the upstream one
            Plug upstreamPubSub = CreatePubSubService(new XDoc("config").Start("downstream").Elem("uri", downstreamUri).End()).WithInternalKey().AtLocalHost;
            Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure);
            var subUri = downstreamDoc["subscription/recipient/uri"].AsUri.AsPublicUri();
            Plug.GlobalCookies.Update(DreamCookie.ParseAllSetCookieNodes(downstreamDoc["subscription/set-cookie"]), subUri);
            Assert.AreEqual("pubsub://*/*", downstreamDoc["subscription/channel"].AsText);
            Assert.AreEqual(upstreamPubSub.Uri.WithoutQuery(), downstreamDoc["uri.owner"].AsUri);
            Assert.AreEqual(upstreamPubSub.Uri.At("subscribers").WithoutQuery(), subUri.WithoutLastSegment());

            // check that our set is properly represented by the upstream service
            DreamMessage upstreamSet = upstreamPubSub.At("subscribers").GetAsync().Wait();
            Assert.IsTrue(upstreamSet.IsSuccessful);
            XDoc upstreamDoc = upstreamSet.ToDocument();
            Assert.AreEqual(1, upstreamDoc["subscription"].ListLength);
            Assert.AreEqual("channel:///foo/*", upstreamDoc["subscription/channel"].AsText);

            // update the subscription set on the upstream service
            XDoc set2 = new XDoc("subscription-set")
               .Elem("uri.owner", downstreamUri)
               .Start("subscription")
                   .Attr("id", "1")
                   .Elem("channel", "channel:///bar/*")
                   .Elem("uri.proxy", downstreamUri.At("publish"))
                   .Start("recipient").Elem("uri", "http:///foo/sub1").End()
               .End();
            DreamMessage subPush = Plug.New(subUri).PostAsync(set2).Wait();
            Assert.IsTrue(subPush.IsSuccessful);
            upstreamSet = upstreamPubSub.At("subscribers").GetAsync().Wait();
            Assert.IsTrue(upstreamSet.IsSuccessful);
            upstreamDoc = upstreamSet.ToDocument();
            Assert.AreEqual(1, upstreamDoc["subscription"].ListLength);
            Assert.AreEqual("channel:///bar/*", upstreamDoc["subscription/channel"].AsText);
        }
Exemplo n.º 38
0
        public void Dispatch_based_on_channel_match_with_different_wikiid_patterns_but_same_proxy_destination()
        {
            var ev = new DispatcherEvent(
                new XDoc("msg"),
                new XUri("event://sales.mindtouch.com/deki/comments/create"),
                new XUri("http://foobar.com/some/comment"));
            var dispatches = new List<DispatcherEvent>();
            XUri testUri = new XUri("http://sales.mindtouch.com/").At(StringUtil.CreateAlphaNumericKey(4));
            int dispatchCounter = 0;
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                if(testUri == plug.Uri) {
                    lock(dispatches) {
                        dispatches.Add(new DispatcherEvent(request));
                        dispatchCounter++;
                    }
                }
                response.Return(DreamMessage.Ok());
            });
            int combinedSetUpdates = 0;
            _dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
            };
            var recipient1Uri = testUri.At("sub1");
            _dispatcher.RegisterSet("abc",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                    .Attr("id", "1")
                    .Elem("channel", "event://sales.mindtouch.com/deki/comments/create")
                    .Elem("channel", "event://sales.mindtouch.com/deki/comments/update")
                    .Elem("uri.proxy", testUri)
                    .Start("recipient").Elem("uri", recipient1Uri).End()
                    .End(), "def");
            var recipient2Uri = testUri.At("sub1");
            _dispatcher.RegisterSet("qwe",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner2")
                    .Start("subscription")
                    .Attr("id", "2")
                    .Elem("channel", "event://*/deki/comments/create")
                    .Elem("channel", "event://*/deki/comments/update")
                    .Elem("uri.proxy", testUri)
                    .Start("recipient").Elem("uri", recipient2Uri).End()
                    .End(), "asd");

            // combinedset updates happen asynchronously, so give'em a chance
            const int expectedCombinedSetUpdates = 2;
            Assert.IsTrue(
                Wait.For(() => combinedSetUpdates >= expectedCombinedSetUpdates, 10.Seconds()),
                string.Format("expected at least {0} combined set updates, gave up after {1}", expectedCombinedSetUpdates, combinedSetUpdates)
            );
            const int expectedDispatches = 2;
            _dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(
                Wait.For(() => {

                    // Doing extra sleeping to improve the chance of catching excess dispatches
                    Thread.Sleep(100);
                    return dispatchCounter == expectedDispatches;
                }, 10.Seconds()),
                string.Format("expected at exactly {0} dispatches, gave up after {1}", expectedDispatches, dispatchCounter)
            );
            var sub1Event = dispatches.Where(x => x.Recipients.Any() && x.Recipients.FirstOrDefault().Uri == recipient1Uri).FirstOrDefault();
            Assert.IsNotNull(sub1Event, "did not receive an event with recipient matching our first subscription");
            Assert.AreEqual(ev.AsDocument(), sub1Event.AsDocument(), "event document is wrong");
            Assert.AreEqual(ev.Id, sub1Event.Id, "event id is wrong");
            var sub2Event = dispatches.Where(x => x.Recipients.Any() && x.Recipients.FirstOrDefault().Uri == recipient2Uri).FirstOrDefault();
            Assert.IsNotNull(sub2Event, "did not receive an event with recipient matching our second subscription");
            Assert.AreEqual(ev.AsDocument(), sub2Event.AsDocument(), "event document is wrong");
            Assert.AreEqual(ev.Id, sub2Event.Id, "event id is wrong");
        }
Exemplo n.º 39
0
 IMockPlug IMockPlug.At(string[] path)
 {
     _uri = _uri.At(path);
     return(this);
 }
Exemplo n.º 40
0
        public void Dispatch_of_event_without_recipients_gets_matched_subscription_recipients_attached()
        {
            var ev = new DispatcherEvent(
                new XDoc("msg"),
                new XUri("channel:///foo/bar"),
                new XUri("http://foobar.com/some/page"));
            var dispatches = new Dictionary<XUri, DispatcherEvent>();
            var testUri = new XUri("http:///").At(StringUtil.CreateAlphaNumericKey(4));
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                dispatches.Add(plug.Uri, new DispatcherEvent(request));
                response.Return(DreamMessage.Ok());
            });
            var combinedSetUpdates = 0;
            _dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
            };
            var r1 = testUri.At("sub1");
            var r2 = testUri.At("sub2");
            _dispatcher.RegisterSet("abc",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                    .Attr("id", "1")
                    .Elem("channel", "channel:///foo/*")
                    .Start("recipient").Elem("uri", r1).End()
                    .End()
                    .Start("subscription")
                    .Attr("id", "2")
                    .Elem("channel", "channel:///foo/baz/*")
                    .Start("recipient").Elem("uri", r2).End()
                    .End(), "def");
            var r3 = testUri.At("sub3");
            var r4 = testUri.At("sub4");
            _dispatcher.RegisterSet("qwe",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner2")
                    .Start("subscription")
                    .Attr("id", "3")
                    .Elem("channel", "channel:///foo/bar")
                    .Start("recipient").Elem("uri", r3).End()
                    .End()
                    .Start("subscription")
                    .Attr("id", "4")
                    .Elem("channel", "channel:///foo/bar/*")
                    .Start("recipient").Elem("uri", r4).End()
                    .End(), "asd");

            // combinedset updates happen asynchronously, so give'em a chance
            const int expectedCombinedSetUpdates = 2;
            Assert.IsTrue(
                Wait.For(() => combinedSetUpdates >= expectedCombinedSetUpdates, 10.Seconds()),
                string.Format("expected at least {0} combined set updates, gave up after {1}", expectedCombinedSetUpdates, combinedSetUpdates)
            );
            _dispatcher.Dispatch(ev);
            const int expectedDispatches = 3;

            // dispatch happens async on a worker thread
            Assert.IsTrue(
                Wait.For(() => {

                    // Doing extra sleeping to improve the chance of catching excess dispatches
                    Thread.Sleep(100);
                    return dispatches.Count == expectedDispatches;
                }, 10.Seconds()),
                string.Format("expected at exactly {0} dispatches, gave up after {1}", expectedDispatches, dispatches.Count)
            );
            Assert.IsTrue(dispatches.ContainsKey(r1), "did not receive an event for sub 1");
            var sub1Event = dispatches[r1];
            Assert.AreEqual(1, sub1Event.Recipients.Length, "wrong number of recipient for sub 1");
            Assert.AreEqual(r1, sub1Event.Recipients[0].Uri, "wrong recipient for sub 1");
            Assert.IsTrue(dispatches.ContainsKey(r3), "did not receive an event for sub 3");
            var sub3Event = dispatches[r3];
            Assert.AreEqual(1, sub3Event.Recipients.Length, "wrong number of recipient for sub 3");
            Assert.AreEqual(r3, sub3Event.Recipients[0].Uri, "wrong recipient for sub 3");
            Assert.IsTrue(dispatches.ContainsKey(r4), "did not receive an event for sub 4");
            var sub4Event = dispatches[r4];
            Assert.AreEqual(1, sub4Event.Recipients.Length, "wrong number of recipient for sub 4");
            Assert.AreEqual(r4, sub4Event.Recipients[0].Uri, "wrong recipient for sub 4");
        }
Exemplo n.º 41
0
        public void TestAppendPath5()
        {
            XUri uri = new XUri("http://www.dummy.com:8081/first/second?query=arg");

            uri = uri.At("foo/bar");
        }
Exemplo n.º 42
0
        public void Dispatch_based_on_channel_match_with_different_wikiid_patterns()
        {
            DispatcherEvent ev = new DispatcherEvent(
                new XDoc("msg"),
                new XUri("event://sales.mindtouch.com/deki/comments/create"),
                new XUri("http://foobar.com/some/comment"));
            Dictionary<XUri, DreamMessage> dispatches = new Dictionary<XUri, DreamMessage>();
            XUri testUri = new XUri("http://sales.mindtouch.com/").At(StringUtil.CreateAlphaNumericKey(4));
            AutoResetEvent resetEvent = new AutoResetEvent(false);
            int dispatchCounter = 0;
            int expectedDispatches = 0;
            MockPlug.Register(testUri, delegate(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
                dispatches.Add(plug.Uri, request);
                dispatchCounter++;
                // ReSharper disable AccessToModifiedClosure
                if(dispatchCounter >= expectedDispatches) {
                    // ReSharper restore AccessToModifiedClosure
                    resetEvent.Set();
                }
                response.Return(DreamMessage.Ok());
            });
            int expectedCombinedSetUpdates = 2;
            int combinedSetUpdates = 0;
            AutoResetEvent setResetEvent = new AutoResetEvent(false);
            _dispatcher.CombinedSetUpdated += delegate {
                combinedSetUpdates++;
                _log.DebugFormat("combinedset updated ({0})", combinedSetUpdates);
                if(combinedSetUpdates >= expectedCombinedSetUpdates) {
                    setResetEvent.Set();
                }
            };
            _dispatcher.RegisterSet("abc",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner1")
                    .Start("subscription")
                    .Attr("id", "1")
                    .Elem("channel", "event://sales.mindtouch.com/deki/comments/create")
                    .Elem("channel", "event://sales.mindtouch.com/deki/comments/update")
                    .Start("recipient").Elem("uri", testUri.At("sub1")).End()
                    .End(), "def");
            _dispatcher.RegisterSet("qwe",
                new XDoc("subscription-set")
                    .Elem("uri.owner", "http:///owner2")
                    .Start("subscription")
                    .Attr("id", "3")
                    .Elem("channel", "event://*/deki/comments/create")
                    .Elem("channel", "event://*/deki/comments/update")
                    .Start("recipient").Elem("uri", testUri.At("sub2")).End()
                    .End(), "asd");

            // combinedset updates happen asynchronously, so give'em a chance
            Assert.IsTrue(setResetEvent.WaitOne(10000, false));
            expectedDispatches = 2;
            _dispatcher.Dispatch(ev);

            // dispatch happens async on a worker thread
            Assert.IsTrue(resetEvent.WaitOne(10000, false));
            Assert.AreEqual(2, dispatches.Count);
            Assert.IsTrue(dispatches.ContainsKey(testUri.At("sub1")));
            Assert.AreEqual(ev.AsMessage().ToDocument(), dispatches[testUri.At("sub1")].ToDocument());
            Assert.AreEqual(ev.Id, dispatches[testUri.At("sub1")].Headers.DreamEventId);
            Assert.IsTrue(dispatches.ContainsKey(testUri.At("sub2")));
        }