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))); }
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()); }
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"); }
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(); }
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(); }
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); }
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)); }
//--- 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); }
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(); }
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(); }
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(); }
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); }
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); }
public XUri PropertyUri(XUri parentUri) { if (ResourceType != Type.PROPERTY) { throw new InvalidOperationException("invalid operation for resource type"); } return(parentUri.At("properties", XUri.DoubleEncodeSegment(Name))); }
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()); }
public IMockInvokeExpectationParameter At(string[] path) { if (_expectedUri == null) { _expectedUri = _baseUri; } _expectedUri = _expectedUri.At(path); return(this); }
//--- 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); }
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); }
//--- 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); }
//--- 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); }
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); }
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()); }
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()); }
//--- 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"); } }
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); }
public void TestAppendPath5() { XUri uri = new XUri("http://www.dummy.com:8081/first/second?query=arg"); uri = uri.At("foo/bar"); }
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); }
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); }
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); }
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); }
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; } } }
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); }
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); }
//--- 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>()); } }
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); }
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"); }
IMockPlug IMockPlug.At(string[] path) { _uri = _uri.At(path); return(this); }
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"); }
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"))); }