public void Pipeline_Process_SequenceOfTwo() { // Arrange var element1 = GetMockFlowElement(); var element2 = GetMockFlowElement(); // Configure the elements element1.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element1", (p) => new TestElementData(p)); tempdata["key"] = "done"; }); element2.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element2", (p) => new TestElementData(p)); tempdata["key"] = "done"; }); // Create the pipeline var pipeline = CreatePipeline( false, false, element1.Object, element2.Object); // Don't create the flow data via the pipeline as we just want // to test Process. IFlowData data = StaticFactories.CreateFlowData(pipeline); data.Process(); // Act pipeline.Process(data); // Assert Assert.IsTrue(data.Errors == null || data.Errors.Count == 0, "Expected no errors"); // Check that the resulting data has the expected values Assert.IsTrue(data.GetDataKeys().Contains("element1"), "data from element 1 is missing in the result"); Assert.IsTrue(data.GetDataKeys().Contains("element2"), "data from element 2 is missing in the result"); Assert.AreEqual("done", data.Get("element1")["key"].ToString()); Assert.AreEqual("done", data.Get("element2")["key"].ToString()); // Check that element 1 was called before element 2. element2.Verify(e => e.Process(It.Is <IFlowData>(d => data.GetDataKeys().Contains("element1"))), "element 1 should have been called before element 2."); }
protected override void ProcessEngine(IFlowData data, IStarSignData aspectData) { // Cast aspectData to StarSignData so the 'setter' is available. StarSignData starSignData = (StarSignData)aspectData; // Get the JSON response which the cloud request engine has // fetched from the cloud service. var requestData = data.Get <CloudRequestData>(); var json = requestData.JsonResponse; // Extract data from json to the aspectData instance. var dictionary = JsonConvert.DeserializeObject <Dictionary <string, object> >(json); // Get the results for the star sign component. var starSign = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase); JsonConvert.PopulateObject(dictionary["starsign"].ToString(), starSign); // Now get the values from the star sign results. starSignData.StarSign = starSign["starsign"].ToString(); }
public void MultiEngineData_SimpleTest() { BuildEngine(false); IFlowData data = _pipeline.CreateFlowData(); EmptyEngineData engineData = data.GetOrAdd( _engine.ElementDataKeyTyped, (f) => new EmptyEngineData( _loggerFactory.CreateLogger <EmptyEngineData>(), f, _engine, null)); engineData.ValueOne = 0; engineData.ValueThree = 50; data.Process(); var result = data.Get <EmptyEngineData>(); Assert.AreEqual(1, result.ValueOne); Assert.AreEqual(50, result.ValueThree); }
private Dictionary <string, string> BuildResponseHeaderDictionary( IFlowData data, PipelineConfig config) { Dictionary <string, string> result = new Dictionary <string, string>(); // Iterate through 'SetHeader*' properties foreach (var property in config.SetHeaderProperties) { // Get the value for this property. var elementData = data.Get(property.Value.PropertyMetaData.Element.ElementDataKey); var propertyValue = elementData[property.Key]; // Extract the string value. var headerValue = GetHeaderValue(propertyValue); // If value is not blank, null or 'unknown' then // add it to the complete value for the associated // header. if (string.IsNullOrEmpty(headerValue) == false && headerValue.Equals("Unknown", StringComparison.OrdinalIgnoreCase) == false) { if (result.TryGetValue(property.Value.ResponseHeaderName, out string currentValue)) { // There is already an entry for this header name // so concatenate the value. result[property.Value.ResponseHeaderName] = $"{currentValue},{headerValue}"; } else { // No entry for this header name so create it. result.Add(property.Value.ResponseHeaderName, headerValue); } } } return(result); }
private void SetUp(IFlowData data) { var host = Host; var protocol = Protocol; bool supportsPromises; if (string.IsNullOrEmpty(host)) { // Try and get the request host name so it can be used to request // the Json refresh in the JavaScript code. data.TryGetEvidence(Constants.EVIDENCE_HOST_KEY, out host); } if (string.IsNullOrEmpty(protocol)) { // Try and get the request protocol so it can be used to request // the JSON refresh in the JavaScript code. data.TryGetEvidence(Constants.EVIDENCE_PROTOCOL, out protocol); } // Couldn't get protocol from anywhere if (string.IsNullOrEmpty(protocol)) { protocol = Constants.DEFAULT_PROTOCOL; } // If device detection is in the Pipeline then we can check // if the client's browser supports promises. // This can be used to customize the JavaScript response. try { var promise = data.GetAs <IAspectPropertyValue <string> >("Promise"); supportsPromises = promise != null && promise.HasValue && promise.Value == "Full"; } catch (PipelineDataException) { supportsPromises = false; } catch (InvalidCastException) { supportsPromises = false; } catch (KeyNotFoundException) { supportsPromises = false; } // Get the JSON include to embed into the JavaScript include. string jsonObject = string.Empty; try { jsonObject = data.Get <IJsonBuilderElementData>().Json; } catch (KeyNotFoundException ex) { throw new PipelineConfigurationException( Messages.ExceptionJsonBuilderNotRun, ex); } // Generate any required parameters for the JSON request. List <string> parameters = new List <string>(); // Any query parameters from this request that were ingested by // the Pipeline are added to the request URL that will appear // in the JavaScript. var queryEvidence = data .GetEvidence() .AsDictionary() .Where(e => e.Key.StartsWith(Core.Constants.EVIDENCE_QUERY_PREFIX, StringComparison.OrdinalIgnoreCase)) .Select(k => { var dotPos = k.Key.IndexOf(Core.Constants.EVIDENCE_SEPERATOR, StringComparison.OrdinalIgnoreCase); return($"{WebUtility.UrlEncode(k.Key.Remove(0, dotPos + 1))}" + $"={WebUtility.UrlEncode(k.Value.ToString())}"); }); parameters.AddRange(queryEvidence); string queryParams = string.Join("&", parameters); string endpoint = Endpoint; Uri url = null; if (string.IsNullOrWhiteSpace(protocol) == false && string.IsNullOrWhiteSpace(host) == false && string.IsNullOrWhiteSpace(endpoint) == false) { var endpointHasSlash = endpoint[0] == '/'; var hostHasSlash = host[host.Length - 1] == '/'; // if there is no slash between host and endpoint then add one. if (endpointHasSlash == false && hostHasSlash == false) { endpoint = $"/{endpoint}"; } // if there are two slashes between host and endpoint then remove one. else if (endpointHasSlash == true && hostHasSlash == true) { endpoint = endpoint.Substring(1); } url = new Uri($"{protocol}://{host}{endpoint}" + (String.IsNullOrEmpty(queryParams) ? "" : $"?{queryParams}")); } // With the gathered resources, build a new JavaScriptResource. BuildJavaScript(data, jsonObject, supportsPromises, url); }
public void ParallelElements_ThreeElements_ValidateParallel() { if (Environment.ProcessorCount < 4) { Assert.Inconclusive("This test cannot be run on a machine with less that 4 processing cores"); } // Arrange var element1 = new Mock <IFlowElement>(); var element2 = new Mock <IFlowElement>(); var element3 = new Mock <IFlowElement>(); element1.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element1", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); element2.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element2", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); element3.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element3", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); _parallelElements = new ParallelElements(_logger.Object, element1.Object, element2.Object, element3.Object); IFlowData data = StaticFactories.CreateFlowData(_pipeline.Object); data.Process(); // Act _parallelElements.Process(data); List <DateTime> startTimes = new List <DateTime>(); startTimes.Add((DateTime)data.Get("element1")["start"]); startTimes.Add((DateTime)data.Get("element2")["start"]); startTimes.Add((DateTime)data.Get("element3")["start"]); List <DateTime> endTimes = new List <DateTime>(); endTimes.Add((DateTime)data.Get("element1")["end"]); endTimes.Add((DateTime)data.Get("element2")["end"]); endTimes.Add((DateTime)data.Get("element3")["end"]); // Assert Assert.IsTrue(data.Errors == null || data.Errors.Count == 0, "Expected no errors"); Assert.IsTrue(startTimes.TrueForAll(dtStart => endTimes.TrueForAll(dtEnd => dtEnd > dtStart)), $"Start times [{string.Join(",", startTimes.Select(t => t.ToString("HH:mm:ss.ffffff")))}] " + $"not before end times [" + $"{string.Join(",", endTimes.Select(t => t.ToString("HH:mm:ss.ffffff")))}]"); for (int i = 0; i < 3; i++) { double ms = endTimes[i].Subtract(startTimes[i]).TotalMilliseconds; Assert.IsTrue(ms < 1100 && ms > 1000, $"Element {i} total time taken was {ms}ms, " + $"which is outside the expected range of 1000-1100"); } }
/// <summary> /// Gets the value of the browser capability, first using the processed /// FlowData, then the base capabilities if the property is not present. /// </summary> /// <param name="key"> /// The name of the browser capability to retrieve. /// </param> /// <returns> /// The browser capability, or element property with the specified key /// name. /// </returns> public override string this[string key] { get { string value = null; // Try getting the value from the FlowData try { var availableElements = FlowData.Pipeline.ElementAvailableProperties; if (key != null && key.Contains(".")) { var keys = key.Split('.'); if (availableElements.ContainsKey(keys[0]) && availableElements[keys[0]].ContainsKey(keys[1]) && availableElements[keys[0]][keys[1]].Available) { var nonStringValue = FlowData.Get(keys[0])[keys[1]]; if (nonStringValue as string != null) { value = nonStringValue as string; } else if (nonStringValue as IDictionary <string, object> != null && keys.Length > 2) { value = IterateDown(keys.Skip(1).ToArray(), nonStringValue as IDictionary <string, object>); } else if (nonStringValue as IDictionary <string, object> != null || nonStringValue as IList <object> != null) { value = Newtonsoft.Json.JsonConvert.SerializeObject(nonStringValue); } else { value = nonStringValue.ToString(); } } } else if (availableElements.Any(i => i.Value.ContainsKey(key))) { var elementKey = availableElements .First(i => i.Value.ContainsKey(key)) .Key; var valueObj = FlowData.Get(elementKey)[key]; if (availableElements[elementKey][key].Type.Equals(typeof(IReadOnlyList <string>))) { value = string.Join("|", ((IEnumerable <object>)valueObj).Select(i => i.ToString())); } else { value = valueObj.ToString(); } } } #pragma warning disable CA1031 // Do not catch general exception types // Regardless of the error that occurs, we want to handle // it in the same way. catch (Exception) #pragma warning restore CA1031 // Do not catch general exception types { // There was an exception, ensure the value is null so it // will be retrieved from the base class. value = null; } // Return the value that was just fetched, or fetch it from the // base class if it was not found. return(value == null ? _baseCaps[key] : value); } }
private void SetUp(IFlowData data) { var host = Host; var protocol = Protocol; bool supportsPromises = false; bool supportsFetch = false; if (string.IsNullOrEmpty(host) && // Try and get the request host name so it can be used to request // the Json refresh in the JavaScript code. data.TryGetEvidence(Constants.EVIDENCE_HOST_KEY, out object hostObj)) { host = hostObj?.ToString() ?? String.Empty; } if (string.IsNullOrEmpty(protocol) && // Try and get the request protocol so it can be used to request // the JSON refresh in the JavaScript code. data.TryGetEvidence(Core.Constants.EVIDENCE_PROTOCOL, out object protocolObj)) { protocol = protocolObj?.ToString() ?? String.Empty; } // Couldn't get protocol from anywhere if (string.IsNullOrEmpty(protocol)) { protocol = Constants.DEFAULT_PROTOCOL; } // If device detection is in the Pipeline then we can check // if the client's browser supports promises. // This can be used to customize the JavaScript response. if (_promisePropertyAvailable) { // Execute this action if one of our expected // exceptions occurs. Action promisesNotAvailable = () => { // Short-circuit future calls, so we don't keep checking // for this property. _promisePropertyAvailable = false; supportsPromises = false; }; try { var promise = data.GetAs <IAspectPropertyValue <string> >("Promise"); supportsPromises = promise != null && promise.HasValue && promise.Value == "Full"; } catch (PropertyMissingException) { promisesNotAvailable(); } catch (PipelineDataException) { promisesNotAvailable(); } catch (InvalidCastException) { promisesNotAvailable(); } catch (KeyNotFoundException) { promisesNotAvailable(); } } // If device detection is in the Pipeline then we can check // if the client's browser supports fetch. // This can be used to customize the JavaScript response. if (_fetchPropertyAvailable) { // Execute this action if one of our expected // exceptions occurs. Action fetchNotAvailable = () => { // Short-circuit future calls, so we don't keep checking // for this property. _fetchPropertyAvailable = false; supportsFetch = false; }; try { var fetch = data.GetAs <IAspectPropertyValue <bool> >("Fetch"); supportsFetch = fetch != null && fetch.HasValue && fetch.Value; } catch (PropertyMissingException) { fetchNotAvailable(); } catch (PipelineDataException) { fetchNotAvailable(); } catch (InvalidCastException) { fetchNotAvailable(); } catch (KeyNotFoundException) { fetchNotAvailable(); } } // Get the JSON include to embed into the JavaScript include. string jsonObject = string.Empty; try { jsonObject = data.Get <IJsonBuilderElementData>().Json; } catch (KeyNotFoundException ex) { throw new PipelineConfigurationException( Messages.ExceptionJsonBuilderNotRun, ex); } var parameters = GetParameters(data); var paramsObject = JsonConvert.SerializeObject(parameters); var sessionId = GetSessionId(data); var sequence = GetSequence(data); string endpoint = Endpoint; Uri url = null; // Check the call-back URL is formatted correctly. if (string.IsNullOrWhiteSpace(protocol) == false && string.IsNullOrWhiteSpace(host) == false && string.IsNullOrWhiteSpace(endpoint) == false) { var endpointHasSlash = endpoint[0] == '/'; var hostHasSlash = host[host.Length - 1] == '/'; // if there is no slash between host and endpoint then add one. if (endpointHasSlash == false && hostHasSlash == false) { endpoint = $"/{endpoint}"; } // if there are two slashes between host and endpoint then remove one. else if (endpointHasSlash == true && hostHasSlash == true) { endpoint = endpoint.Substring(1); } url = new Uri($"{protocol}://{host}{endpoint}"); } // With the gathered resources, build a new JavaScriptResource. BuildJavaScript(data, jsonObject, sessionId, sequence, supportsPromises, supportsFetch, url, paramsObject); }