예제 #1
0
        public void TwoThreadsInterleavingFailuresStillRetriesOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string thread1Auth;
            string thread1AuthRetry;
            string thread2Auth;
            string thread2AuthRetry;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);

            // Simulate a 401 error on one threads
            dut.RejectCredentials(tracer, thread1Auth);
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1);
            gitProcess.CredentialRejections["mock://repoUrl"][0].BasicAuthString.ShouldEqual(thread1Auth);

            // That thread then retries
            dut.TryGetCredentials(tracer, out thread1AuthRetry, out error).ShouldEqual(true);

            // The second thread fails with the old PAT
            dut.RejectCredentials(tracer, thread2Auth);
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1, "Should not have rejected a second time");
            gitProcess.CredentialRejections["mock://repoUrl"][0].BasicAuthString.ShouldEqual(thread1Auth, "Should only have rejected thread1's initial credential");

            // The second thread should be able to get a PAT
            dut.TryGetCredentials(tracer, out thread2AuthRetry, out error).ShouldEqual(true, error);
        }
예제 #2
0
        public void AuthShouldBackoffAfterFirstRetryFailure()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");

            dut.RejectCredentials(tracer, authString);
            dut.IsBackingOff.ShouldEqual(false, "Should not backoff after credentials initially rejected");
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1);

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration");
            dut.IsBackingOff.ShouldEqual(false, "Should not backoff after successfully getting credentials");

            dut.RejectCredentials(tracer, authString);
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff after rejecting credentials");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(2);
        }
예제 #3
0
        public void TwoThreadsFailAtOnceStillRetriesOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string authString;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);

            // Simulate a 401 error on two threads
            dut.RejectCredentials(tracer, authString);
            dut.RejectCredentials(tracer, authString);
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1);
            gitProcess.CredentialRejections["mock://repoUrl"][0].BasicAuthString.ShouldEqual(authString);

            // Both threads should still be able to get a PAT for retry purposes
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "The second thread caused back off when it shouldn't");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);
        }
예제 #4
0
        public void ContinuesToBackoffIfTryGetCredentialsFails()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");
            dut.RejectCredentials(tracer, authString);
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1);

            gitProcess.ShouldFail = true;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "Succeeded despite GitProcess returning failure");
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff if failed to get credentials");

            dut.RejectCredentials(tracer, authString);
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff if failed to get credentials");
            gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(1);
        }
예제 #5
0
        public void TwoThreadsInterleavingFailuresStillRetriesOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockEnlistment enlistment = new MockEnlistment();
            MockGitProcess gitProcess = new MockGitProcess(enlistment);

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string thread1Auth;
            string thread2Auth;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);

            // Simulate a 401 error on one threads
            dut.RevokeAndCheckCanRetry(thread1Auth).ShouldEqual(true);

            // That thread then retries
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);

            // The second thread fails with the old PAT
            dut.RevokeAndCheckCanRetry(thread2Auth).ShouldEqual(true);

            // The second thread should be able to get a PAT
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);
        }
예제 #6
0
        protected ScalarEnlistment CreateEnlistment(string enlistmentRootPath, GitAuthentication authentication)
        {
            string gitBinPath = ScalarPlatform.Instance.GitInstallation.GetInstalledGitBinPath();

            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                this.ReportErrorAndExit("Error: " + ScalarConstants.GitIsNotInstalledError);
            }

            ScalarEnlistment enlistment = null;

            try
            {
                enlistment = ScalarEnlistment.CreateFromDirectory(
                    enlistmentRootPath,
                    gitBinPath,
                    authentication,
                    createWithoutRepoURL: !this.validateOriginURL);
            }
            catch (InvalidRepoException e)
            {
                this.ReportErrorAndExit(
                    "Error: '{0}' is not a valid Scalar enlistment. {1}",
                    enlistmentRootPath,
                    e.Message);
            }

            return(enlistment);
        }
예제 #7
0
        public void TwoThreadsInterleavingFailuresShouldntStompASuccess()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string thread1Auth;
            string thread2Auth;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);

            // Simulate a 401 error on one threads
            dut.Revoke(thread1Auth);

            // That thread then retries and succeeds
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);
            dut.ConfirmCredentialsWorked(thread1Auth);

            // If the second thread fails with the old PAT, it shouldn't stomp the new PAT
            dut.Revoke(thread2Auth);

            // The second thread should be able to get a PAT
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);
            thread2Auth.ShouldEqual(thread1Auth, "The second thread stomp the first threads good auth string");
        }
예제 #8
0
        public static GVFSEnlistment CreateFromDirectory(
            string directory,
            string gitBinRoot,
            string gvfsHooksRoot,
            GitAuthentication authentication,
            bool createWithoutRepoURL = false)
        {
            if (Directory.Exists(directory))
            {
                string errorMessage;
                string enlistmentRoot;
                if (!GVFSPlatform.Instance.TryGetGVFSEnlistmentRoot(directory, out enlistmentRoot, out errorMessage))
                {
                    throw new InvalidRepoException($"Could not get enlistment root. Error: {errorMessage}");
                }

                if (createWithoutRepoURL)
                {
                    return(new GVFSEnlistment(enlistmentRoot, string.Empty, gitBinRoot, gvfsHooksRoot, authentication));
                }

                return(new GVFSEnlistment(enlistmentRoot, gitBinRoot, gvfsHooksRoot, authentication));
            }

            throw new InvalidRepoException($"Directory '{directory}' does not exist");
        }
예제 #9
0
        public void TwoThreadsInterleavingFailuresStillRetriesOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string thread1Auth;
            string thread2Auth;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true);

            // Simulate a 401 error on one threads
            dut.Revoke(thread1Auth);

            // That thread then retries
            dut.TryGetCredentials(tracer, out thread1Auth, out error).ShouldEqual(true);

            // The second thread fails with the old PAT
            dut.Revoke(thread2Auth);

            // The second thread should be able to get a PAT
            dut.TryGetCredentials(tracer, out thread2Auth, out error).ShouldEqual(true, error);
        }
예제 #10
0
        public static ScalarEnlistment CreateFromDirectory(
            string directory,
            string gitBinRoot,
            GitAuthentication authentication,
            bool createWithoutRepoURL = false)
        {
            if (Directory.Exists(directory))
            {
                string enlistmentRoot;
                string workingDirectory;

                if (!TryGetScalarEnlistmentRoot(directory, out enlistmentRoot, out workingDirectory))
                {
                    throw new InvalidRepoException(directory, $"Could not get enlistment root.");
                }

                if (createWithoutRepoURL)
                {
                    return(new ScalarEnlistment(enlistmentRoot, workingDirectory, string.Empty, gitBinRoot, authentication));
                }

                return(new ScalarEnlistment(enlistmentRoot, workingDirectory, null, gitBinRoot, authentication));
            }

            throw new InvalidRepoException(directory, $"Directory '{directory}' does not exist");
        }
예제 #11
0
 // Existing, configured enlistment
 private GVFSEnlistment(string enlistmentRoot, string gitBinPath, GitAuthentication authentication)
     : this(
         enlistmentRoot,
         null,
         gitBinPath,
         authentication)
 {
 }
예제 #12
0
            public void Execute(GitAuthentication authentication)
            {
                this.ValidatePathParameter(this.EnlistmentRootPathParameter);

                this.PreCreateEnlistment();
                GVFSEnlistment enlistment = this.CreateEnlistment(this.EnlistmentRootPathParameter, authentication);

                this.Execute(enlistment);
            }
예제 #13
0
            private GVFSEnlistment CreateEnlistment(string enlistmentRootPath, GitAuthentication authentication)
            {
                string gitBinPath = GVFSPlatform.Instance.GitInstallation.GetInstalledGitBinPath();

                if (string.IsNullOrWhiteSpace(gitBinPath))
                {
                    this.ReportErrorAndExit("Error: " + GVFSConstants.GitIsNotInstalledError);
                }

                string hooksPath = null;

                if (GVFSPlatform.Instance.UnderConstruction.RequiresDeprecatedGitHooksLoader)
                {
                    // On Windows, the soon-to-be deprecated GitHooksLoader tries to call out to the hooks process without
                    // its full path, so we have to pass the path along to our background git processes via the PATH
                    // environment variable. On Mac this is not needed because we just copy our own hook directly into
                    // the .git/hooks folder, and once Windows does the same, this hooksPath can be removed (from here
                    // and all the classes that handle it on the way to GitProcess)

                    hooksPath = ProcessHelper.WhereDirectory(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName);
                    if (hooksPath == null)
                    {
                        this.ReportErrorAndExit("Could not find " + GVFSPlatform.Instance.Constants.GVFSHooksExecutableName);
                    }
                }

                GVFSEnlistment enlistment = null;

                try
                {
                    if (this.validateOriginURL)
                    {
                        enlistment = GVFSEnlistment.CreateFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication);
                    }
                    else
                    {
                        enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication);
                    }

                    if (enlistment == null)
                    {
                        this.ReportErrorAndExit(
                            "Error: '{0}' is not a valid GVFS enlistment",
                            enlistmentRootPath);
                    }
                }
                catch (InvalidRepoException e)
                {
                    this.ReportErrorAndExit(
                        "Error: '{0}' is not a valid GVFS enlistment. {1}",
                        enlistmentRootPath,
                        e.Message);
                }

                return(enlistment);
            }
예제 #14
0
        public HttpRequestor(ITracer tracer, GitAuthentication authentication)
        {
            this.client         = new HttpClient();
            this.client.Timeout = TimeSpan.FromMinutes(HttpTimeoutMinutes);
            this.authentication = authentication;

            this.Tracer = tracer;

            this.userAgentHeader = new ProductInfoHeaderValue(ProcessHelper.GetEntryClassName(), ProcessHelper.GetCurrentProcessVersion());
        }
예제 #15
0
            private GVFSEnlistment CreateEnlistment(string enlistmentRootPath, GitAuthentication authentication)
            {
                string gitBinPath = GVFSPlatform.Instance.GitInstallation.GetInstalledGitBinPath();

                if (string.IsNullOrWhiteSpace(gitBinPath))
                {
                    this.ReportErrorAndExit("Error: " + GVFSConstants.GitIsNotInstalledError);
                }

                string hooksPath;

                if (GVFSPlatform.Instance.IsUnderConstruction)
                {
                    hooksPath = "hooksUnderConstruction";
                }
                else
                {
                    hooksPath = ProcessHelper.WhereDirectory(GVFSPlatform.Instance.Constants.GVFSHooksExecutableName);
                    if (hooksPath == null)
                    {
                        this.ReportErrorAndExit("Could not find " + GVFSPlatform.Instance.Constants.GVFSHooksExecutableName);
                    }
                }

                GVFSEnlistment enlistment = null;

                try
                {
                    if (this.validateOriginURL)
                    {
                        enlistment = GVFSEnlistment.CreateFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication);
                    }
                    else
                    {
                        enlistment = GVFSEnlistment.CreateWithoutRepoUrlFromDirectory(enlistmentRootPath, gitBinPath, hooksPath, authentication);
                    }

                    if (enlistment == null)
                    {
                        this.ReportErrorAndExit(
                            "Error: '{0}' is not a valid GVFS enlistment",
                            enlistmentRootPath);
                    }
                }
                catch (InvalidRepoException e)
                {
                    this.ReportErrorAndExit(
                        "Error: '{0}' is not a valid GVFS enlistment. {1}",
                        enlistmentRootPath,
                        e.Message);
                }

                return(enlistment);
            }
예제 #16
0
        public HttpRequestor(ITracer tracer, GitAuthentication authentication, int maxConnections)
        {
            this.client         = new HttpClient();
            this.client.Timeout = TimeSpan.FromMinutes(HttpTimeoutMinutes);
            this.authentication = authentication;

            this.Tracer = tracer;

            ServicePointManager.DefaultConnectionLimit = maxConnections;

            this.userAgentHeader = new ProductInfoHeaderValue(ProcessHelper.GetEntryClassName(), ProcessHelper.GetCurrentProcessVersion());
        }
예제 #17
0
        protected Enlistment(
            string enlistmentRoot,
            string workingDirectoryRoot,
            string repoUrl,
            string gitBinPath,
            bool flushFileBuffersForPacks,
            GitAuthentication authentication)
        {
            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                throw new ArgumentException("Path to git.exe must be set");
            }

            this.EnlistmentRoot           = enlistmentRoot;
            this.WorkingDirectoryRoot     = workingDirectoryRoot;
            this.DotGitRoot               = Path.Combine(this.WorkingDirectoryRoot, ScalarConstants.DotGit.Root);
            this.GitBinPath               = gitBinPath;
            this.FlushFileBuffersForPacks = flushFileBuffersForPacks;

            GitProcess gitProcess = new GitProcess(this);

            if (repoUrl != null)
            {
                this.RepoUrl = repoUrl;
            }
            else
            {
                GitProcess.ConfigResult originResult = gitProcess.GetOriginUrl();
                if (!originResult.TryParseAsString(out string originUrl, out string error))
                {
                    if (!gitProcess.TryGetRemotes(out string[] remotes, out error))
                    {
                        throw new InvalidRepoException(this.WorkingDirectoryRoot, $"Failed to load remotes with error: {error}");
                    }

                    if (remotes.Length > 0)
                    {
                        GitProcess.ConfigResult remoteResult = gitProcess.GetFromLocalConfig($"remote.{remotes[0]}.url");
                        if (!remoteResult.TryParseAsString(out originUrl, out error))
                        {
                            originUrl = null;
                        }
                    }
                }

                this.RepoUrl = originUrl?.Trim() ?? string.Empty;
            }

            this.Authentication = authentication ?? new GitAuthentication(gitProcess, this.RepoUrl, this.WorkingDirectoryRoot);
        }
예제 #18
0
파일: HttpRequestor.cs 프로젝트: yyqyu/GVFS
        public HttpRequestor(ITracer tracer, RetryConfig retryConfig, GitAuthentication authentication)
        {
            this.client = new HttpClient(new HttpClientHandler()
            {
                UseDefaultCredentials = true
            });
            this.client.Timeout = retryConfig.Timeout;
            this.RetryConfig    = retryConfig;
            this.authentication = authentication;

            this.Tracer = tracer;

            this.userAgentHeader = new ProductInfoHeaderValue(ProcessHelper.GetEntryClassName(), ProcessHelper.GetCurrentProcessVersion());
        }
예제 #19
0
        protected Enlistment(
            string enlistmentRoot,
            string workingDirectoryRoot,
            string localStorageRoot,
            string repoUrl,
            string gitBinPath,
            string gvfsHooksRoot,
            bool flushFileBuffersForPacks,
            GitAuthentication authentication)
        {
            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                throw new ArgumentException("Path to git.exe must be set");
            }

            this.EnlistmentRoot              = enlistmentRoot;
            this.WorkingDirectoryRoot        = workingDirectoryRoot;
            this.WorkingDirectoryBackingRoot = localStorageRoot;
            this.DotGitRoot               = Path.Combine(this.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Root);
            this.GitBinPath               = gitBinPath;
            this.GVFSHooksRoot            = gvfsHooksRoot;
            this.FlushFileBuffersForPacks = flushFileBuffersForPacks;

            GitProcess gitProcess = new GitProcess(this);

            if (repoUrl != null)
            {
                this.RepoUrl = repoUrl;
            }
            else
            {
                GitProcess.ConfigResult originResult = gitProcess.GetOriginUrl();
                if (!originResult.TryParseAsString(out string originUrl, out string error))
                {
                    throw new InvalidRepoException("Could not get origin url. git error: " + error);
                }

                if (originUrl == null)
                {
                    throw new InvalidRepoException("Could not get origin url. remote 'origin' is not configured for this repo.'");
                }

                this.RepoUrl = originUrl.Trim();
            }

            this.Authentication = authentication ?? new GitAuthentication(gitProcess, this.RepoUrl);
        }
예제 #20
0
        public void BackoffIsNotInEffectAfterSuccess()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            for (int i = 0; i < 5; ++i)
            {
                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get credential on iteration " + i + ": " + error);
                dut.Revoke(authString);
                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration " + i + ": " + error);
                dut.ConfirmCredentialsWorked(authString);
                dut.IsBackingOff.ShouldEqual(false, "Should reset backoff after successfully refreshing credentials");
            }
        }
예제 #21
0
        public void ShouldOnlyRetryAuthOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockEnlistment enlistment = new MockEnlistment();
            MockGitProcess gitProcess = new MockGitProcess(enlistment);

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");

            dut.RevokeAndCheckCanRetry(authString).ShouldEqual(true, "Should retry once");

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration");

            dut.RevokeAndCheckCanRetry(authString).ShouldEqual(false, "Should not retry more than once");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
        }
예제 #22
0
        public void GitProcessFailuresAreRetried()
        {
            MockTracer     tracer     = new MockTracer();
            MockEnlistment enlistment = new MockEnlistment();
            MockGitProcess gitProcess = new MockGitProcess(enlistment);

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            gitProcess.ShouldFail = true;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "Succeeded despite GitProcess returning failure");

            dut.RevokeAndCheckCanRetry(authString).ShouldEqual(true, "Should retry once");

            gitProcess.ShouldFail = false;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get credential on retry");
        }
예제 #23
0
        protected HttpRequestor(ITracer tracer, RetryConfig retryConfig, Enlistment enlistment)
        {
            this.RetryConfig = retryConfig;

            this.authentication = enlistment.Authentication;

            this.Tracer = tracer;

            HttpClientHandler httpClientHandler = new HttpClientHandler()
            {
                UseDefaultCredentials = true
            };

            this.authentication.ConfigureHttpClientHandlerSslIfNeeded(this.Tracer, httpClientHandler, enlistment.CreateGitProcess());

            this.client = new HttpClient(httpClientHandler)
            {
                Timeout = retryConfig.Timeout
            };

            this.userAgentHeader = new ProductInfoHeaderValue(ProcessHelper.GetEntryClassName(), ProcessHelper.GetCurrentProcessVersion());
        }
예제 #24
0
        public void AuthShouldBackoffAfterFirstRetryFailure()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");

            dut.Revoke(authString);
            dut.IsBackingOff.ShouldEqual(false, "Should not backoff after credentials initially revoked");

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration");
            dut.IsBackingOff.ShouldEqual(false, "Should not backoff after successfully getting credentials");

            dut.Revoke(authString);
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff after revoking credentials");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
        }
예제 #25
0
        public void ContinuesToBackoffIfTryGetCredentialsFails()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");
            dut.Revoke(authString);

            gitProcess.ShouldFail = true;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "Succeeded despite GitProcess returning failure");
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff if failed to get credentials");

            dut.Revoke(authString);
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
            dut.IsBackingOff.ShouldEqual(true, "Should continue to backoff if failed to get credentials");
        }
예제 #26
0
        public void GitProcessFailuresAreRetried()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            gitProcess.ShouldFail = true;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "Succeeded despite GitProcess returning failure");

            // Reboke should be a no-op as valid credentials have not been stored
            dut.Revoke(authString);
            dut.IsBackingOff.ShouldEqual(false, "Should not backoff if there were no credentials to revoke");

            gitProcess.ShouldFail = false;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get credential on retry");
        }
예제 #27
0
        public void CanRetryManyTimesIfTheresSomeSuccess()
        {
            MockTracer     tracer     = new MockTracer();
            MockEnlistment enlistment = new MockEnlistment();
            MockGitProcess gitProcess = new MockGitProcess(enlistment);

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            for (int i = 0; i < 5; ++i)
            {
                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get credential on iteration " + i + ": " + error);

                dut.RevokeAndCheckCanRetry(authString).ShouldEqual(true, "Did not retry after revoke on iteration: " + i);

                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration " + i + ": " + error);

                dut.ConfirmCredentialsWorked(authString);
            }
        }
예제 #28
0
        public void DoesNotRetryIfTryGetCredentialsFails()
        {
            MockTracer     tracer     = new MockTracer();
            MockEnlistment enlistment = new MockEnlistment();
            MockGitProcess gitProcess = new MockGitProcess(enlistment);

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get initial credential");

            dut.RevokeAndCheckCanRetry(authString).ShouldEqual(true, "Should retry once");

            gitProcess.ShouldFail = true;

            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "Succeeded despite GitProcess returning failure");

            dut.RevokeAndCheckCanRetry(authString).ShouldEqual(false, "Should not retry if GitProcess fails after retry");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(false, "TryGetCredential should not succeed during backoff");
        }
예제 #29
0
        public void TwoThreadsFailAtOnceStillRetriesOnce()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess);

            string authString;
            string error;

            // Populate an initial PAT on two threads
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);

            // Simulate a 401 error on two threads
            dut.Revoke(authString);
            dut.Revoke(authString);

            // Both threads should still be able to get a PAT for retry purposes
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "The second thread caused back off when it shouldn't");
            dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true);
        }
예제 #30
0
        public void BackoffIsNotInEffectAfterSuccess()
        {
            MockTracer     tracer     = new MockTracer();
            MockGitProcess gitProcess = this.GetGitProcess();

            GitAuthentication dut = new GitAuthentication(gitProcess, "mock://repoUrl");

            dut.TryInitializeAndRequireAuth(tracer, out _);

            string authString;
            string error;

            for (int i = 0; i < 5; ++i)
            {
                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to get credential on iteration " + i + ": " + error);
                dut.RejectCredentials(tracer, authString);
                dut.TryGetCredentials(tracer, out authString, out error).ShouldEqual(true, "Failed to retry getting credential on iteration " + i + ": " + error);
                dut.ApproveCredentials(tracer, authString);
                dut.IsBackingOff.ShouldEqual(false, "Should reset backoff after successfully refreshing credentials");
                gitProcess.CredentialRejections["mock://repoUrl"].Count.ShouldEqual(i + 1, $"Should have {i+1} credentials rejection");
                gitProcess.CredentialApprovals["mock://repoUrl"].Count.ShouldEqual(i + 1, $"Should have {i+1} credential approvals");
            }
        }