Exemple #1
0
        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.");
        }
Exemple #2
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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");
            }
        }
Exemple #7
0
        /// <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);
            }
        }
Exemple #8
0
        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);
        }