public void TestRestoreGSMFromLSMsRangeWithGarbageInGSM()
        {
            ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerLoadPolicy.Lazy);

            RangeShardMap<int> rsm = smm.GetRangeShardMap<int>(RecoveryManagerTests.s_rangeShardMapName);

            Assert.IsNotNull(rsm);
            IList<ShardLocation> sls = new List<ShardLocation>();
            int i = 0;
            List<RangeMapping<int>> ranges = new List<RangeMapping<int>>();
            foreach (string dbName in RecoveryManagerTests.s_shardedDBs)
            {
                ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, dbName);
                sls.Add(sl);
                Shard s = rsm.CreateShard(sl);
                Assert.IsNotNull(s);
                var r = rsm.CreateRangeMapping(new Range<int>(1 + i * 10, 10 + i * 10), s);
                Assert.IsNotNull(r);
                ranges.Add(r);
                i++;
            }

            // Perturb the mappings in the GSM.
            using (SqlConnection conn = new SqlConnection(Globals.ShardMapManagerTestConnectionString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand(String.Format("update {0}.__ShardManagement.ShardMappingsGlobal set MaxValue = MaxValue + 1, MinValue = MinValue + 1", Globals.ShardMapManagerDatabaseName), conn))
                {
                    cmd.ExecuteNonQuery();
                }
            }

            RecoveryManager rm = new RecoveryManager(smm);

            // Validate that we detect the inconsistencies in all the LSMs.
            foreach (ShardLocation sl in sls)
            {
                IEnumerable<RecoveryToken> gs = rm.DetectMappingDifferences(sl);

                Assert.AreEqual(1, gs.Count(), "The test environment was not expecting more than one local shardmap.");

                // Briefly validate that 
                foreach (RecoveryToken g in gs)
                {
                    var kvps = rm.GetMappingDifferences(g);
                    Assert.AreEqual(2, kvps.Keys.Count, "The count of differences does not match the expected.");
                }
            }

            // Recover the LSM from the GSM
            rm.RebuildMappingsOnShardMapManagerFromShards(sls);

            // Validate that we fixed all the inconsistencies.
            foreach (ShardLocation sl in sls)
            {
                IEnumerable<RecoveryToken> gs = rm.DetectMappingDifferences(sl);
                // Briefly validate that 
                foreach (RecoveryToken g in gs)
                {
                    var kvps = rm.GetMappingDifferences(g);
                    Assert.AreEqual(0, kvps.Keys.Count, "There were still differences after resolution.");
                }
            }
        }
        public void TestRestoreGSMFromLSMsRange()
        {
            ShardMapManager smm = ShardMapManagerFactory.GetSqlShardMapManager(
                Globals.ShardMapManagerConnectionString,
                ShardMapManagerLoadPolicy.Lazy);

            RangeShardMap<int> rsm = smm.GetRangeShardMap<int>(RecoveryManagerTests.s_rangeShardMapName);

            Assert.IsNotNull(rsm);
            IList<ShardLocation> sls = new List<ShardLocation>();
            int i = 0;
            List<RangeMapping<int>> ranges = new List<RangeMapping<int>>();
            foreach (string dbName in RecoveryManagerTests.s_shardedDBs)
            {
                ShardLocation sl = new ShardLocation(Globals.ShardMapManagerTestsDatasourceName, dbName);
                sls.Add(sl);
                Shard s = rsm.CreateShard(sl);
                Assert.IsNotNull(s);
                var r = rsm.CreateRangeMapping(new Range<int>(1 + i * 10, 10 + i * 10), s);
                Assert.IsNotNull(r);
                ranges.Add(r);
                i++;
            }

            // Delete all mappings from GSM
            using (SqlConnection conn = new SqlConnection(Globals.ShardMapManagerTestConnectionString))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand(String.Format("delete from {0}.__ShardManagement.ShardMappingsGlobal", Globals.ShardMapManagerDatabaseName), conn))
                {
                    cmd.ExecuteNonQuery();
                }
            }

            RecoveryManager rm = new RecoveryManager(smm);

            // Validate that we detect the inconsistencies in all the LSMs.
            foreach (ShardLocation sl in sls)
            {
                IEnumerable<RecoveryToken> gs = rm.DetectMappingDifferences(sl);

                Assert.AreEqual(1, gs.Count(), "The test environment was not expecting more than one local shardmap.");

                // Briefly validate that 
                foreach (RecoveryToken g in gs)
                {
                    var kvps = rm.GetMappingDifferences(g);
                    Assert.AreEqual(1, kvps.Keys.Count, "The count of differences does not match the expected.");

                    foreach (var kvp in kvps)
                    {
                        ShardRange range = kvp.Key;
                        MappingLocation mappingLocation = kvp.Value;
                        Assert.AreEqual(MappingLocation.MappingInShardOnly, mappingLocation, "An unexpected difference between global and local shardmaps was detected. This is likely a false positive and implies a bug in the detection code.");
                    }
                }
            }

            // Recover the LSM from the GSM
            rm.RebuildMappingsOnShardMapManagerFromShards(sls);

            // Validate that we fixed all the inconsistencies.
            foreach (ShardLocation sl in sls)
            {
                IEnumerable<RecoveryToken> gs = rm.DetectMappingDifferences(sl);
                // Briefly validate that 
                foreach (RecoveryToken g in gs)
                {
                    var kvps = rm.GetMappingDifferences(g);
                    Assert.AreEqual(0, kvps.Keys.Count, "There were still differences after resolution.");
                }
            }
        }