/// <summary>
        ///     Given a sequence, add dummy characters based on the strategy and seed data passed.
        /// </summary>
        /// <param name="sequence">
        ///     The base sequence without dummy characters.
        /// </param>
        /// <param name="strategy">
        ///     The strategy to be used.
        /// </param>
        /// <param name="seed">
        ///     The seed value to be used.
        /// </param>
        /// <returns>
        ///     Character sequence with dummy characters merged into it, based on the strategy used.
        /// </returns>
        public static string AddDummyCharacters(string sequence, ObfuscationStrategy strategy, int seed)
        {
            if (string.IsNullOrEmpty(sequence))
            {
                return(sequence);
            }

            var sb = new StringBuilder();

            sb.Append(sequence);

            int dummyCharacterIndex = 0, insertionIndex = 0;

            while (sb.Length < Settings.MinimumLength)
            {
                if (strategy == ObfuscationStrategy.Constant)
                {
                    // Compute insertionIndex in a constant way (using hash).
                    // While allowing the possibility of first and last index.
                    // Note that insertionIndex can exceed sb.Length by 1 (i.e. insert after last character).
                    int hash = Math.Abs(sb.ToString().GetStableHashCode());
                    // int hash = Math.Abs(sb.ToString().GetHashCode());
                    insertionIndex = (hash ^ seed) % sb.Length;
                    if ((hash % seed % 3) > (sb.Length / 2))
                    {
                        insertionIndex++;
                    }

                    // Compute 'randomized' dummy character index constantly (using hash).
                    // Note that insertionIndex cannot exceed dummyCharacterSet.Length.
                    dummyCharacterIndex = (hash ^ seed) % Settings.DummyCharacterSet.Length;
                }
                else
                {
                    // Randomize insertion index.
                    // Note that Min-Max boundary has inclusive min, exclusive max
                    insertionIndex      = random.Next(0, sb.Length + 1); // insertion can be at last character (i.e. sb.Length)
                    dummyCharacterIndex = random.Next(0, Settings.DummyCharacterSet.Length);
                }

                sb.Insert(insertionIndex, Settings.DummyCharacterSet[dummyCharacterIndex]);
            }

            return(sb.ToString());
        }
        public void EnsureCorrectConversion(ObfuscationStrategy strategy)
        {
            var obfuscator = ObfuscatorFactory.NewInstance;

            obfuscator.Strategy = strategy;

            for (int i = 0; i < 100000; i++)
            {
                string obfuscatedValue   = obfuscator.Obfuscate(i);
                int    deobfuscatedValue = obfuscator.Deobfuscate(obfuscatedValue);

                if (deobfuscatedValue != i)
                {
                    // Assert fails.
                    Assert.True(false);
                }
            }
        }
        public void EnsureNoCollision(ObfuscationStrategy strategy)
        {
            var obfuscator = ObfuscatorFactory.NewInstance;

            obfuscator.Strategy = strategy;

            var hashSet = new HashSet <string>();

            for (int i = 0; i < 1000000; i++)
            {
                string obfuscatedValue = obfuscator.Obfuscate(i);

                // HashSet.Add will return false if element already exists.
                if (!hashSet.Add(obfuscatedValue))
                {
                    // Assert fails.
                    Assert.True(false);
                }
            }
        }
        public void TestAddDummyCharacters(ObfuscationStrategy strategy)
        {
            var validCharacters = Settings.ValidCharacterSet;
            var dummyCharacters = Settings.DummyCharacterSet;

            // Generate valid input by taking first 3 characters of validCharacters.
            string validInput = new string(validCharacters.Dictionary.Select(x => x.Value).Take(3).ToArray());

            /* Perform operation under test with constant strategy, */
            var obfuscator = ObfuscatorFactory.NewInstance;
            int seed       = obfuscator.Seed;
            var testResult = ObfuscatorHelper.AddDummyCharacters(validInput, strategy, seed);

            // Remove all valid characters from result.
            var dummyResult = testResult.ToCharArray().ToList();

            dummyResult.RemoveAll(x => validCharacters.ContainsValue(x));

            // Ensure result only contains dummy characters.
            Assert.True(dummyResult.All(x => dummyCharacters.Contains(x)));
        }