예제 #1
0
        public void Operate(string testId, SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener)
        {
            Logger.Log(TraceLevel.Notice, testId, Stage.Open, new { sessionStartInfo.AgentSessionId });
            Stopwatch stopwatch = Stopwatch.StartNew();

            TaskListener <RunningSession> taskListener = new TaskListener <RunningSession>(
                (runningSession) => OnComplete_(sessionStartInfo, listener, runningSession, stopwatch, testId),
                (ex) =>
            {
                var webEx = CommonUtils.GetInnerException <WebException>(ex);
                if (webEx != null && webEx.Status != WebExceptionStatus.Success)
                {
                    CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, ex,
                                                       new { webExceptionStatus = webEx.Status }, testId);
                    listener.OnFail(ex.InnerException);
                    return;
                }
                OnFail_(stopwatch, sessionStartInfo, listener, testId);
            }
                );

            try
            {
                ServerConnector.StartSession(taskListener, sessionStartInfo);
            }
            catch (Exception e)
            {
                listener.OnFail(e);
            }
        }
예제 #2
0
        public virtual void PostDomCapture(TaskListener <string> listener, string domJson, params string[] testIds)
        {
            Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.UploadStart);
            try
            {
                byte[] binData = Encoding.UTF8.GetBytes(domJson);
                Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.UploadResource,
                           new { UncompressedDataSize = binData.Length });
                using (MemoryStream compressedStream = new MemoryStream())
                {
                    using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
                    {
                        zipStream.Write(binData, 0, binData.Length);
                    }
                    binData = compressedStream.ToArray();
                }

                Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.UploadResource,
                           new { CompressedDataSize = binData.Length });

                UploadData_(listener, binData, "application/octet-stream", "application/json", testIds);
            }
            catch (Exception ex)
            {
                CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.UploadResource, ex, testIds);
                listener.OnFail(new EyesException($"PostDomSnapshot failed: {ex.Message}", ex));
            }
        }
예제 #3
0
        public void Operate(string testId, SessionStopInfo sessionStopInfo, TaskListener <TestResults> listener)
        {
            if (sessionStopInfo == null)
            {
                TestResults testResults = new TestResults();
                testResults.Status = TestResultsStatus.NotOpened;
                listener.OnComplete(testResults);
                return;
            }

            TaskListener <TestResults> taskListener = new TaskListener <TestResults>(
                (testResults) =>
            {
                Logger.Log(TraceLevel.Notice, testId, Stage.Close, new { testResults.Status });
                testResults.IsNew = sessionStopInfo.RunningSession.IsNewSession;
                testResults.Url   = sessionStopInfo.RunningSession.Url;
                Logger.Verbose(testResults.ToString());
                testResults.ServerConnector = ServerConnector;
                listener.OnComplete(testResults);
            },
                (ex) =>
            {
                listener.OnFail(new EyesException("Failed closing test", ex));
            });

            try
            {
                Logger.Log(TraceLevel.Notice, testId, Stage.Close, new { sessionStopInfo });
                ServerConnector.EndSession(taskListener, sessionStopInfo);
            }
            catch (Exception e)
            {
                listener.OnFail(e);
            }
        }
예제 #4
0
        private void UploadData_(TaskListener <string> listener, byte[] bytes, string contentType, string mediaType,
                                 string[] testIds)
        {
            RenderingInfo renderingInfo = GetRenderingInfo();
            string        targetUrl     = renderingInfo?.ResultsUrl?.AbsoluteUri;

            if (targetUrl == null)
            {
                listener.OnComplete(null);
                return;
            }

            Guid guid = Guid.NewGuid();

            targetUrl = targetUrl.Replace("__random__", guid.ToString());
            Logger.Log(TraceLevel.Info, testIds, Stage.General, StageType.UploadStart, new { mediaType, targetUrl });

            HttpRequestMessage request = CreateHttpRequestMessageForUpload_(targetUrl, bytes, contentType, mediaType);

            httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>(
                                             response =>
            {
                if (response == null)
                {
                    throw new NullReferenceException("response is null");
                }
                listener.OnComplete(targetUrl);
            },
                                             ex => listener.OnFail(ex)),
                                         request, Logger, new BackoffProvider(2), TimeSpan.FromMinutes(2));
        }
예제 #5
0
        public virtual void CheckResourceStatus(TaskListener <bool?[]> taskListener, HashSet <string> testIds, string renderId, HashObject[] hashes)
        {
            renderId = renderId ?? "NONE";
            HttpRequestMessage request = CreateUfgHttpWebRequest_($"/query/resources-exist?rg_render-id={renderId}", content: hashes);

            Logger.Log(TraceLevel.Info, testIds, Stage.ResourceCollection, StageType.CheckResource, new { hashes, renderId });
            SendUFGAsyncRequest_(taskListener, request);
        }
예제 #6
0
 protected virtual void SendUFGAsyncRequest_ <T>(TaskListener <T> taskListener, HttpRequestMessage request) where T : class
 {
     httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>(
                                      response =>
     {
         if (response == null)
         {
             throw new NullReferenceException("response is null");
         }
         taskListener.OnComplete(response.DeserializeBody <T>(true));
     },
                                      ex => taskListener.OnFail(ex)), request, Logger, new BackoffProvider());
 }
예제 #7
0
 public void MatchWindow(string testId, MatchWindowData data, TaskListener <MatchResult> listener)
 {
     try
     {
         Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.MatchStart, new { matchWindowData = data });
         LoggingListener <MatchResult> loggingListener = new LoggingListener <MatchResult>(listener, Logger, testId);
         ServerConnector.MatchWindow(loggingListener, data, testId);
     }
     catch (Exception ex)
     {
         CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.MatchComplete, ex, testId);
         listener.OnFail(ex);
     }
 }
예제 #8
0
        public virtual void Render(TaskListener <List <RunningRender> > renderListener, IList <IRenderRequest> requests)
        {
            ArgumentGuard.NotNull(requests, nameof(requests));
            string fullAgentId = AgentId;

            foreach (IRenderRequest renderRequest in requests)
            {
                renderRequest.AgentId = fullAgentId;
                Logger.Log(TraceLevel.Info, renderRequest.TestId, Stage.Render, new { renderRequest });
            }

            HttpRequestMessage request = CreateUfgHttpWebRequest_("render", content: requests);

            SendUFGAsyncRequest_(renderListener, request);
        }
예제 #9
0
        protected virtual void StartSessionInternal(TaskListener <RunningSession> taskListener, SessionStartInfo startInfo)
        {
            ArgumentGuard.NotNull(startInfo, nameof(startInfo));

            var body = new
            {
                StartInfo = startInfo
            };

            try
            {
                EnsureHttpClient_();
                httpClient_.PostJson(
                    new TaskListener <HttpResponseMessage>(
                        response =>
                {
                    if (response == null)
                    {
                        throw new NullReferenceException("response is null");
                    }
                    // response.DeserializeBody disposes the response object's stream,
                    // rendering all of its properties unusable, including StatusCode.
                    HttpStatusCode responseStatusCode = response.StatusCode;
                    RunningSession runningSession;
                    if (responseStatusCode == HttpStatusCode.ServiceUnavailable)
                    {
                        runningSession = new RunningSession();
                        runningSession.ConcurrencyFull = true;
                    }
                    else
                    {
                        runningSession = response.DeserializeBody <RunningSession>(
                            true, serializer_, HttpStatusCode.OK, HttpStatusCode.Created);
                        if (runningSession.isNewSession_ == null)
                        {
                            runningSession.isNewSession_ = responseStatusCode == HttpStatusCode.Created;
                        }
                        runningSession.ConcurrencyFull = false;
                    }
                    taskListener.OnComplete(runningSession);
                }, ex => taskListener.OnFail(ex))
                    , "api/sessions/running", body);
            }
            catch (Exception ex)
            {
                throw new EyesException($"StartSession failed: {ex.Message}", ex);
            }
        }
예제 #10
0
        private void OnFail_(Stopwatch stopwatch, SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener, string testId)
        {
            TimeSpan sleepDuration = TimeSpan.FromSeconds(2);

            if (stopwatch.Elapsed > TIME_TO_WAIT_FOR_OPEN)
            {
                isServerConcurrencyLimitReached_ = false;
                listener.OnFail(new EyesException("Timeout in start session"));
                return;
            }

            try
            {
                Thread.Sleep(sleepDuration);
                if (stopwatch.Elapsed.TotalSeconds >= 30)
                {
                    sleepDuration = TimeSpan.FromSeconds(10);
                }
                else if (stopwatch.Elapsed.TotalSeconds >= 10)
                {
                    sleepDuration = TimeSpan.FromSeconds(5);
                }

                Logger.Verbose("Trying startSession again");
                ServerConnector.StartSession(
                    new TaskListener <RunningSession>(
                        (runningSession) => OnComplete_(sessionStartInfo, listener, runningSession, stopwatch, testId),
                        (ex) =>
                {
                    var socketEx = CommonUtils.GetInnerException <SocketException>(ex);
                    if (socketEx != null && socketEx.SocketErrorCode == SocketError.ConnectionRefused)
                    {
                        listener.OnFail(ex.InnerException);
                        return;
                    }

                    OnFail_(stopwatch, sessionStartInfo, listener, testId);
                }
                        ),
                    sessionStartInfo);
            }
            catch (Exception e)
            {
                CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, StageType.Retry, e, testId);
                listener.OnFail(e);
            }
        }
예제 #11
0
        protected virtual void EndSessionInternal(TaskListener <TestResults> taskListener, SessionStopInfo sessionStopInfo)
        {
            ArgumentGuard.NotNull(sessionStopInfo, nameof(sessionStopInfo));
            ArgumentGuard.NotNull(sessionStopInfo.RunningSession, nameof(sessionStopInfo.RunningSession));

            httpClient_.DeleteJson(new TaskListener <HttpResponseMessage>(
                                       response =>
            {
                if (response == null)
                {
                    throw new NullReferenceException("response is null");
                }
                taskListener.OnComplete(response.DeserializeBody <TestResults>(true));
            },
                                       ex => taskListener.OnFail(ex)
                                       ), $"api/sessions/running/{sessionStopInfo.RunningSession.Id}", sessionStopInfo);
        }
예제 #12
0
        public virtual void RenderStatusById(TaskListener <List <RenderStatusResults> > taskListener,
                                             IList <string> testIds, IList <string> renderIds)
        {
            ArgumentGuard.NotNull(renderIds, nameof(renderIds));
            ArgumentGuard.NotNull(testIds, nameof(testIds));

            for (int i = 0; i < testIds.Count; i++)
            {
                Logger.Log(TraceLevel.Info, testIds[i], Stage.Render, StageType.RenderStatus,
                           new { renderId = renderIds[i] });
            }

            HttpRequestMessage request = CreateUfgHttpWebRequest_("render-status", content: renderIds);

            // request.Timeout = 1000;

            SendUFGAsyncRequest_(taskListener, request);
        }
예제 #13
0
        private void OnComplete_(SessionStartInfo sessionStartInfo, TaskListener <RunningSession> listener,
                                 RunningSession runningSession, Stopwatch stopwatch, string testId)
        {
            if (runningSession.ConcurrencyFull)
            {
                isServerConcurrencyLimitReached_ = true;
                Logger.Log(TraceLevel.Warn, testId, Stage.Open, StageType.Retry,
                           new { message = "Failed starting test, concurrency is fully used. Trying again." });
                OnFail_(stopwatch, sessionStartInfo, listener, testId);
                return;
            }

            isServerConcurrencyLimitReached_ = false;
            Logger.Log(TraceLevel.Notice, testId, Stage.Open, StageType.Complete,
                       new { message = $"Server session ID is {runningSession.Id}" });
            //Logger.SessionId(runningSession.SessionId);
            listener.OnComplete(runningSession);
        }
예제 #14
0
        public void TryUploadImage(string testId, MatchWindowData data, TaskListener taskListener)
        {
            AppOutput appOutput = data.AppOutput;

            if (appOutput.ScreenshotUrl != null)
            {
                taskListener.OnComplete();
                return;
            }

            // Getting the screenshot bytes
            TaskListener <string> uploadListener = new TaskListener <string>(
                (url) =>
            {
                if (url == null)
                {
                    Logger.Verbose("Got null url from upload. Test id: {0}", testId);
                    appOutput.ScreenshotUrl = null;
                    taskListener.OnFail(new EyesException("Failed uploading image"));
                    return;
                }
                Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.UploadComplete, new { url });
                appOutput.ScreenshotUrl = url;
                appOutput.ClearScreenshotBytes();
                taskListener.OnComplete();
            },
                (ex) =>
            {
                appOutput.ScreenshotUrl = null;
                taskListener.OnFail(new EyesException("Failed uploading image", ex));
            }
                );

            try
            {
                Logger.Log(TraceLevel.Info, testId, Stage.Check, StageType.UploadStart,
                           new { dataLength = appOutput.ScreenshotBytes.Length });
                ServerConnector.UploadImage(uploadListener, appOutput.ScreenshotBytes, testId);
            }
            catch (Exception ex)
            {
                taskListener.OnFail(ex);
            }
        }
예제 #15
0
        public void RenderPutResource(TaskListener <HttpResponseMessage> listener, string renderId, IVGResource resource)
        {
            ArgumentGuard.NotNull(resource, nameof(resource));
            byte[] content = resource.Content;
            ArgumentGuard.NotNull(content, nameof(resource.Content));

            string hash        = resource.Sha256;
            string contentType = resource.ContentType?.Split(';')[0];

            Logger.Log(TraceLevel.Info, resource.TestIds, Stage.Render,
                       new { resourceHash = hash, resourceUrl = resource.Url, renderId });

            HttpRequestMessage request = CreateUfgHttpWebRequest_($"/resources/sha256/{hash}?render-id={renderId}",
                                                                  method: "PUT", contentType: contentType, mediaType: contentType ?? "application/octet-stream",
                                                                  content: content);

            httpClient_.SendAsyncRequest(listener, request, Logger, new BackoffProvider());
            Logger.Verbose("future created.");
        }
예제 #16
0
        protected virtual void MatchWindowImpl_(TaskListener <MatchResult> listener, MatchWindowData data, string[] testIds)
        {
            string url = string.Format("api/sessions/running/{0}", data.RunningSession.Id);

            Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.MatchStart);
            httpClient_.PostJson(new TaskListener <HttpResponseMessage>(
                                     response =>
            {
                Logger.Log(TraceLevel.Notice, testIds, Stage.Check, StageType.MatchComplete,
                           new { response?.StatusCode });
                if (response == null)
                {
                    throw new NullReferenceException("response is null");
                }
                MatchResult matchResult = response.DeserializeBody <MatchResult>(true);
                Logger.Log(TraceLevel.Info, testIds, Stage.Check, StageType.MatchComplete, new { matchResult });
                listener.OnComplete(matchResult);
            },
                                     e => listener.OnFail(e)
                                     ), url, data);
        }
예제 #17
0
        public void MatchWindow(TaskListener <MatchResult> listener, MatchWindowData data, params string[] testIds)
        {
            ArgumentGuard.NotNull(data, nameof(data));

            if (data.AppOutput.ScreenshotBytes != null)
            {
                UploadImage(new TaskListener <string>(
                                returnedUrl =>
                {
                    Logger.Log(TraceLevel.Notice, testIds, Stage.General, StageType.UploadComplete, new { returnedUrl });
                    if (returnedUrl == null)
                    {
                        listener.OnFail(new EyesException($"{nameof(MatchWindow)} failed: could not upload image to storage service."));
                        return;
                    }
                    try
                    {
                        data.AppOutput.ScreenshotUrl = returnedUrl;
                        MatchWindowImpl_(listener, data, testIds);
                    }
                    catch (Exception ex)
                    {
                        throw new EyesException($"{nameof(MatchWindow)} failed: {ex.Message}", ex);
                    }
                },
                                ex => listener.OnFail(ex)
                                ), data.AppOutput.ScreenshotBytes, testIds);
            }
            else if (data.AppOutput.ScreenshotUrl != null)
            {
                MatchWindowImpl_(listener, data, testIds);
            }
            else
            {
                throw new EyesException("Failed to upload image.");
            }
        }
예제 #18
0
        public virtual void GetJobInfo(TaskListener <IList <JobInfo> > listener, IList <IRenderRequest> renderRequests)
        {
            ArgumentGuard.NotNull(renderRequests, nameof(renderRequests));
            string[] testIds = renderRequests.Select(bi => bi.TestId).ToArray();
            Logger.Log(TraceLevel.Notice, testIds, Stage.Open, StageType.JobInfo, new { renderRequests });
            try
            {
                HttpRequestMessage request = CreateUfgHttpWebRequest_("job-info", content: renderRequests);
                Logger.Log(TraceLevel.Info, testIds, Stage.Open, StageType.RequestSent, new { request.RequestUri });

                httpClient_.SendAsyncRequest(new TaskListener <HttpResponseMessage>(
                                                 response =>
                {
                    JObject[] jobInfosUnparsed = response.DeserializeBody <JObject[]>(true);
                    List <JobInfo> jobInfos    = new List <JobInfo>();
                    foreach (JObject jobInfoUnparsed in jobInfosUnparsed)
                    {
                        JobInfo jobInfo = new JobInfo
                        {
                            Renderer        = jobInfoUnparsed.Value <string>("renderer"),
                            EyesEnvironment = jobInfoUnparsed.Value <object>("eyesEnvironment")
                        };
                        jobInfos.Add(jobInfo);
                    }
                    Logger.Log(TraceLevel.Info, testIds, Stage.Open, StageType.RequestCompleted, new { request.RequestUri });
                    listener.OnComplete(jobInfos);
                },
                                                 ex => listener.OnFail(ex)
                                                 ), request, Logger, new BackoffProvider());
            }
            catch (Exception e)
            {
                CommonUtils.LogExceptionStackTrace(Logger, Stage.Open, StageType.JobInfo, e, testIds);
                listener.OnFail(e);
            }
        }
예제 #19
0
 /// <summary>
 /// Starts a new session.
 /// </summary>
 public void StartSession(TaskListener <RunningSession> taskListener, SessionStartInfo sessionStartInfo)
 {
     StartSessionInternal(taskListener, sessionStartInfo);
 }
예제 #20
0
        public override void Run()
        {
            while (inputQueue_.Count > 0)
            {
                Tuple <string, MatchWindowData> nextInput = inputQueue_.Dequeue();
                string id = nextInput.Item1;
                lock (lockObject_) inUploadProcess_.Add(id);
                MatchWindowData matchWindowData = nextInput.Item2;
                TryUploadImage(id, matchWindowData,
                               new TaskListener(
                                   () =>
                {
                    lock (lockObject_)
                    {
                        inUploadProcess_.Remove(id);
                        matchWindowQueue_.Enqueue(Tuple.Create(id, matchWindowData));
                    }
                },
                                   (e) =>
                {
                    lock (lockObject_)
                    {
                        inUploadProcess_.Remove(id);
                        Logger.Log(TraceLevel.Error, id, Stage.Check, StageType.UploadComplete, new { nextInput });
                        errorQueue_.Add(Tuple.Create(id, e));
                    }
                }));
            }

            while (matchWindowQueue_.Count > 0)
            {
                Tuple <string, MatchWindowData> nextInput = matchWindowQueue_.Dequeue();
                string id = nextInput.Item1;
                lock (lockObject_) inMatchWindowProcess_.Add(id);
                MatchWindowData            matchWindowData = nextInput.Item2;
                TaskListener <MatchResult> listener        = new TaskListener <MatchResult>(
                    (taskResponse) =>
                {
                    lock (lockObject_)
                    {
                        inMatchWindowProcess_.Remove(id);
                        outputQueue_.Add(Tuple.Create(id, taskResponse));
                    }
                },
                    (e) =>
                {
                    lock (lockObject_)
                    {
                        inMatchWindowProcess_.Remove(id);
                        Logger.Log(TraceLevel.Error, id, Stage.Check, StageType.MatchComplete, new { nextInput });
                        errorQueue_.Add(new Tuple <string, Exception>(id, new EyesException("Match window failed")));
                    }
                });

                try
                {
                    MatchWindow(id, matchWindowData, listener);
                }
                catch (Exception ex)
                {
                    CommonUtils.LogExceptionStackTrace(Logger, Stage.Check, StageType.MatchStart, ex, id);
                    listener.OnFail(ex);
                }
            }
            ;
        }
예제 #21
0
 /// <summary>
 /// Ends the input running session.
 /// </summary>
 public void EndSession(TaskListener <TestResults> taskListener, SessionStopInfo sessionStopInfo)
 {
     EndSessionInternal(taskListener, sessionStopInfo);
 }
예제 #22
0
 public LoggingListener(TaskListener <T> internalListener, Logger logger,
                        string message, [CallerMemberName] string caller = null, params string[] testIds)
     : this(internalListener.OnComplete, internalListener.OnFail, logger, caller, message, testIds)
 {
 }
예제 #23
0
 public void UploadImage(TaskListener <string> listener, byte[] screenshotBytes, string[] testIds)
 {
     UploadData_(listener, screenshotBytes, "image/png", "image/png", testIds);
 }