public void DetectsCollision()
        {
            string pw      = TestValues.GetPw(2);
            string foundPw = string.Empty;
            var    logic   = new LogicImplementation();

            logic.CollisionFound  += (p) => { foundPw = p; };
            logic.ProgressChanged += (c, l) => { };
            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                var startTime = DateTime.Now;
                while ((foundPw == string.Empty) && ((DateTime.Now - startTime).TotalMilliseconds < 1000))
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception: {ex.GetType().ToString()} - {ex.Message} ");
            }
            logic.AbortSearch();
            Assert.IsFalse((foundPw == string.Empty), $"Logic - does not return a collision through its 'CollisionFound' event.");
            Assert.IsTrue((pw == foundPw), $"Logic - returns wrong value for a collision: \'{foundPw}\', expected: \'{pw}\'.");
        }
        public void HonorsAbortRequest()
        {
            string pw           = TestValues.GetPw(5);
            int    eventCounter = 0;
            var    logic        = new LogicImplementation();

            logic.CollisionFound  += (p) => { };
            logic.ProgressChanged += (c, l) => { eventCounter++; };
            var startTime = DateTime.Now;

            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                startTime = DateTime.Now;
                while ((eventCounter == 0) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception: {ex.GetType().ToString()} - {ex.Message} ");
            }
            logic.AbortSearch();
            eventCounter = 0;
            startTime    = DateTime.Now;
            while ((eventCounter <= 1) && ((DateTime.Now - startTime).TotalMilliseconds < 200))
            {
                Thread.Sleep(5);
            }
            Assert.IsTrue((eventCounter <= 1), $"Logic - AbortSearch does not stop background Task.");
        }
        public void HonorsReportInterval()
        {
            int    testInterval = 20;
            string pw           = TestValues.GetPw(5);
            ulong  pwCount      = 0;
            var    intervals    = new List <int>();
            var    previousTime = DateTime.Now;
            var    logic        = new LogicImplementation();
            var    cancelSource = new CancellationTokenSource();
            var    cancelToken  = cancelSource.Token;
            var    progress     = new Progress <ulong>((count) =>
            {
                pwCount    = count;
                DateTime t = DateTime.Now;
                intervals.Add((int)(t - previousTime).TotalMilliseconds);
                previousTime = t;
            });
            var collisionFound = new Progress <string>((result) => { });

            logic.ReportInterval = testInterval;
            var task      = Task.Run(() => { logic.SearchCollisions(Sha1Hash.CalculateFromString(pw), progress, collisionFound, cancelToken); });
            var startTime = DateTime.Now;

            while ((intervals.Count() < 4) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
            {
                Thread.Sleep(5);
            }
            Assert.IsFalse((intervals.Count() == 0), $"SearchCollisions - does not report progress through its 'progress' object.");
            cancelSource.Cancel();
            intervals.RemoveAt(0);
            int interval = (intervals[0] + intervals[1] + intervals[2]) / 3;

            Assert.IsTrue((Math.Abs(testInterval - interval) < 20),
                          $"SearchCollisions - does not report progress at requested interval of {testInterval}ms, was {interval}ms.");
        }
        private void buttonCalculateHash_Click(object sender, EventArgs e)
        {
            string password = textBoxPassword.Text;

            password         = password.ToUpper();
            passwordHash     = Sha1Hash.CalculateFromString(password).ToString();
            textBoxHash.Text = passwordHash;

            textBoxPassword.Text           = password;
            buttonAbort.Enabled            = true;
            buttonSearchCollisions.Enabled = true;
        }
        public void CanStartSearchAfterAbort()
        {
            // start and abort a search.
            string pw           = TestValues.GetPw(5);
            string foundPw      = string.Empty;
            int    eventCounter = 0;
            var    logic        = new LogicImplementation();

            logic.CollisionFound  += (p) => { foundPw = p; };
            logic.ProgressChanged += (c, l) => { eventCounter++; };
            var startTime = DateTime.Now;

            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                startTime = DateTime.Now;
                while ((eventCounter == 0) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception: {ex.GetType().ToString()} - {ex.Message} ");
            }
            logic.AbortSearch();
            eventCounter = 0;
            startTime    = DateTime.Now;
            while ((eventCounter <= 1) && ((DateTime.Now - startTime).TotalMilliseconds < 200))
            {
                Thread.Sleep(5);
            }
            Assert.IsTrue((eventCounter <= 1), $"Logic - AbortSearch does not stop background Task.");
            // and start a second one
            pw      = TestValues.GetPw(2);
            foundPw = string.Empty;
            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                startTime = DateTime.Now;
                while ((foundPw == string.Empty) && ((DateTime.Now - startTime).TotalMilliseconds < 1000))
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception when started after an abort request: {ex.GetType().ToString()} - {ex.Message} ");
            }
            Assert.IsFalse((foundPw == string.Empty), $"Logic - does not return a collision when started after an abort request.");
            logic.AbortSearch();
        }
        public void ReportsProgress()
        {
            string pw             = TestValues.GetPw(5);
            ulong  pwCount        = 0;
            var    logic          = new LogicImplementation();
            var    cancelSource   = new CancellationTokenSource();
            var    cancelToken    = cancelSource.Token;
            var    progress       = new Progress <ulong>((count) => { pwCount = count; });
            var    collisionFound = new Progress <string>((result) => { });
            var    task           = Task.Run(() => { logic.SearchCollisions(Sha1Hash.CalculateFromString(pw), progress, collisionFound, cancelToken); });
            var    startTime      = DateTime.Now;

            while ((pwCount == 0) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
            {
                Thread.Sleep(5);
            }
            cancelSource.Cancel();
            Assert.IsFalse((pwCount == 0), $"SearchCollisions - does not report progress through its 'progress' object.");
        }
        public void ChecksForNullEvents()
        {
            string pw    = TestValues.GetPw(5);
            var    logic = new LogicImplementation();

            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                var startTime = DateTime.Now;
                while ((DateTime.Now - startTime).TotalMilliseconds < 200)
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception: {ex.GetType().ToString()} - {ex.Message} ");
            }
            logic.AbortSearch();
        }
        public void DetectsCollision()
        {
            string pw             = TestValues.GetPw(2);
            string foundPw        = string.Empty;
            var    logic          = new LogicImplementation();
            var    cancelSource   = new CancellationTokenSource();
            var    cancelToken    = cancelSource.Token;
            var    progress       = new Progress <ulong>((count) => { });
            var    collisionFound = new Progress <string>((result) => { foundPw = result; cancelSource.Cancel(); });
            var    task           = Task.Run(() => { logic.SearchCollisions(Sha1Hash.CalculateFromString(pw), progress, collisionFound, cancelToken); });
            var    startTime      = DateTime.Now;

            while ((foundPw == string.Empty) && ((DateTime.Now - startTime).TotalMilliseconds < 1000))
            {
                Thread.Sleep(5);
            }
            Assert.IsFalse((foundPw == string.Empty), $"SearchCollisions - does not return a collision through its 'collisionFound' progress object.");
            Assert.IsTrue((pw == foundPw), $"SearchCollisions - returns wrong value for a collision: \'{foundPw}\', expected: \'{pw}\'.");
            cancelSource.Cancel();
        }
        public void HonorsCancelRequest()
        {
            string pw             = TestValues.GetPw(5);
            ulong  pwCount        = 0;
            var    logic          = new LogicImplementation();
            var    cancelSource   = new CancellationTokenSource();
            var    cancelToken    = cancelSource.Token;
            var    progress       = new Progress <ulong>((count) => { pwCount = count; });
            var    collisionFound = new Progress <string>((result) => { });
            var    task           = Task.Run(() => { logic.SearchCollisions(Sha1Hash.CalculateFromString(pw), progress, collisionFound, cancelToken); });
            var    startTime      = DateTime.Now;

            while ((pwCount == 0) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
            {
                Thread.Sleep(5);
            }
            cancelSource.Cancel();
            var taskAborted = task.Wait(300);

            Assert.IsTrue(taskAborted, $"SearchCollisions - does not stop Task after 'Cancel' request.");
        }
        public void SearchCollisions(Sha1Hash hash, IProgress <ulong> progress, IProgress <string> collisionFound, CancellationToken cancelToken)
        {
            ulong             count             = 0;
            PasswordGenerator passwordGenerator = new PasswordGenerator();

            foreach (string password in passwordGenerator)
            {
                if (hash == Sha1Hash.CalculateFromString(password))
                {
                    collisionFound.Report(password);
                    break;
                }
                lengthTestedPassword = passwordGenerator.PasswordLength;
                count++;
                progress.Report(count);
                Thread.Sleep(50);
                if (cancelToken.IsCancellationRequested)
                {
                    break;
                }
            }
        }
        public void ReportsProgress()
        {
            string pw      = TestValues.GetPw(5);
            ulong  pwCount = 0;
            var    logic   = new LogicImplementation();

            logic.CollisionFound  += (p) => { };
            logic.ProgressChanged += (c, l) => { pwCount = c; };
            try
            {
                logic.StartSearchCollisionsTask(Sha1Hash.CalculateFromString(pw));
                var startTime = DateTime.Now;
                while ((pwCount == 0) && ((DateTime.Now - startTime).TotalMilliseconds < 500))
                {
                    Thread.Sleep(5);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Logic - \'StartSearchCollisionsTask\' method throws an exception: {ex.GetType().ToString()} - {ex.Message} ");
            }
            logic.AbortSearch();
            Assert.IsFalse((pwCount == 0), $"Logic does not report # of passwords tested through its 'ProgressChanged' event.");
        }