示例#1
0
        public void RetrieveUserGroups(UserModel user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }
            if (userMapper.AreGroupsLoaded(user))
            {
                return;
            }
            user.Groups.EnableSync();

            Task.Factory.StartNew(() =>
            {
                user.Groups.Clear();
                var groups        = repository.GetUserGroups(user.Name);
                var groupModels   = groups.Select(g => groupMapper.GetModel(g, includeDummy: false));
                var modelComparer = KeyComparer <GroupModel> .OrderBy(m => m.Name);
                foreach (GroupModel model in groupModels)
                {
                    int index = user.Groups.ToSublist().UpperBound(model, modelComparer);
                    user.Groups.Insert(index, model);
                }
            }).ContinueWith(
                t => onErrorOccurred(t.Exception),
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnFaulted,
                TaskScheduler.FromCurrentSynchronizationContext()
                );
        }
示例#2
0
        /// <summary>
        /// Construct a tree from given storage, using the specified comparer of key
        /// </summary>
        /// <param name="keySerializer">Tool to serialize node keys.</param>
        /// <param name="valueSerializer">Tool to serialize node values<param>
        /// <param name="recordStorage">Underlying tool for storage.</param>
        /// <param name="keyComparer">Key comparer.</param>
        public TreeDiskNodeManager(ISerializer <K> keySerializer
                                   , ISerializer <V> valueSerializer
                                   , IRecordStorage recordStorage
                                   , IComparer <K> keyComparer)
        {
            if (recordStorage == null)
            {
                throw new ArgumentNullException("nodeStorge");
            }

            this.recordStorage = recordStorage;
            this.serializer    = new TreeDiskNodeSerializer <K, V> (this, keySerializer, valueSerializer);
            this.KeyComparer   = keyComparer;
            this.EntryComparer = Comparer <Tuple <K, V> > .Create((a, b) => {
                return(KeyComparer.Compare(a.Item1, b.Item1));
            });

            // The first record of nodeStorage stores id of root node,
            // if this record do not exist at the time this index instanitate,
            // then attempt to create it
            var firstBlockData = recordStorage.Find(1u);

            if (firstBlockData != null)
            {
                this.rootNode = Find(BufferHelper.ReadBufferUInt32(firstBlockData, 0));
            }
            else
            {
                this.rootNode = CreateFirstRoot();
            }
        }
示例#3
0
        public void RetrieveGroupMembers(GroupModel group)
        {
            if (group == null)
            {
                throw new ArgumentNullException("group");
            }
            if (groupMapper.AreUsersLoaded(group))
            {
                return;
            }
            group.Users.EnableSync();

            Task.Factory.StartNew(() =>
            {
                group.Users.Clear();
                var users         = repository.GetGroupMembers(group.Name);
                var userModels    = users.Select(u => userMapper.GetModel(u, includeDummy: false));
                var modelComparer = KeyComparer <UserModel> .OrderBy(m => m.FullName);
                foreach (UserModel model in userModels)
                {
                    int index = group.Users.ToSublist().UpperBound(model, modelComparer);
                    group.Users.Insert(index, model);
                }
            }).ContinueWith(
                t => onErrorOccurred(t.Exception),
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnFaulted,
                TaskScheduler.FromCurrentSynchronizationContext()
                );
        }
示例#4
0
        public void TestKeyComparer_OrderBy_WithComparer_NullKeySelector_Throws()
        {
            Func <int, int> keySelector = null;
            Comparer <int>  keyComparer = Comparer <int> .Default;

            KeyComparer <int> .OrderBy <int>(keySelector, keyComparer);
        }
示例#5
0
        public NodeQueue(Func <Node <TItem>, TValue> valueSelector)
        {
            _valueSelector = valueSelector;
            var keyComparer = new KeyComparer();

            _items = new SortedList <TValue, Node <TItem> >(keyComparer);
        }
示例#6
0
        public void TestKeyComparer_OrderBy_NullKeyComparer_Throws()
        {
            Func <int, int> keySelector = i => i;
            Comparer <int>  keyComparer = null;

            KeyComparer <int> .OrderBy <int>(keySelector, keyComparer);
        }
示例#7
0
        public static ArraySegment <int> SortRank(ArraySegment <T> values, KeyComparer <T> comparer = default(KeyComparer <T>))
        {
            KVPComparer <T, int> kvComparer;

            if (EqualityComparer <KeyComparer <T> > .Default.Equals(comparer, default(KeyComparer <T>)))
            {
                kvComparer = _kvComparer;
            }
            else
            {
                kvComparer = new KVPComparer <T, int>(comparer, KeyComparer <int> .Default);
            }

            if (_sorted == null || values.Count > _sorted.Length)
            {
                _sorted = new KeyValuePair <T, int> [values.Count];
                _ranked = new int[values.Count];
            }
            for (int i = 0; i < values.Count; i++)
            {
                _sorted[i] = new KeyValuePair <T, int>(values.Array[values.Offset + i], i);
            }
            // TODO use two arrays instead of the _sorted one and use the pool
            Array.Sort(_sorted, kvComparer);
            for (int i = 0; i < _sorted.Length; i++)
            {
                _ranked[_sorted[i].Value] = i;
            }
            Array.Clear(_sorted, 0, values.Count);
            return(new ArraySegment <int>(_ranked));
        }
示例#8
0
 public TValue GetOrAdd <TKey, TValue>(
     TKey key,
     Func <TKey, TValue> valueFactory,
     KeyComparer <TKey> keyComparer = null)
 {
     return(CreateScoped <TKey, TValue>(keyComparer).GetOrAdd(key, valueFactory));
 }
示例#9
0
        internal long BinarySearchUnchecked(int index, int length, T value, KeyComparer <T> comparer)
        {
            int lo = index;
            int hi = index + length - 1;

            while (lo <= hi)
            {
                int i     = lo + ((hi - lo) >> 1);
                int order = comparer.Compare(this[i], value);

                if (order == 0)
                {
                    return(i);
                }
                if (order < 0)
                {
                    lo = i + 1;
                }
                else
                {
                    hi = i - 1;
                }
            }
            return(~lo);
        }
示例#10
0
        public void TestKeyComparer_OrderByDescending_WithComparison_NullKeySelector_Throws()
        {
            Func <int, int>      keySelector   = null;
            Func <int, int, int> keyComparison = Comparer <int> .Default.Compare;

            KeyComparer <int> .OrderByDescending <int>(keySelector, keyComparison);
        }
示例#11
0
        public override int Compare(TObject x, TObject y)
        {
            var xValue = KeySelector(x);
            var yValue = KeySelector(y);

            return(KeyComparer.Compare(xValue, yValue));
        }
示例#12
0
        public void TestKeyComparer_OrderByDescending_NullKeyComparison_Throws()
        {
            Func <int, int>      keySelector   = i => i;
            Func <int, int, int> keyComparison = null;

            KeyComparer <int> .OrderByDescending <int>(keySelector, keyComparison);
        }
示例#13
0
        public void Nums_Abs()
        {
            var nums  = new[] { 47, -32, -54, 18, 62, -71, 58 };
            var byAbs = new SortedSet <int>(nums, KeyComparer.Create((int n) => Math.Abs(n)));

            EnumerableAssert.AreEqual(new[] { 18, -32, 47, -54, 58, 62, -71 }, byAbs);
        }
示例#14
0
        public void TryFind_Test()
        {
            const int count = 100;

            var keys     = RandomHelper.UniqueSequence(_random, count);
            var values   = RandomHelper.UniqueSequence(_random, count);
            var items    = keys.Zip(values, (k, v) => new KeyValuePair <int, int>(k, v)).ToArray();
            var comparer = new KeyComparer <int, int>();

            var node = CreateTree(items, comparer);

            foreach (var item in items)
            {
                var searched = new KeyValuePair <int, int>(item.Key, 12345);
                KeyValuePair <int, int> foundItem;

                var result = node.TryFind(searched, comparer, out foundItem);

                Assert.IsTrue(result);
                Assert.AreEqual(item, foundItem);
            }

            var absentKeys = GetAbsentElements(keys);

            foreach (var key in absentKeys)
            {
                var searched = new KeyValuePair <int, int>(key, 123);
                KeyValuePair <int, int> foundItem;

                var result = node.TryFind(searched, comparer, out foundItem);

                Assert.IsFalse(result);
            }
        }
示例#15
0
        private static IReadOnlyDictionary <IEnumerable <int>, IEnumerable <int>?> PrepareDictionaryWithLists()
        {
            int dicOfDicsCapacity = 6;
            var keyComparer       = new KeyComparer();
            var dicOfDics         = new Dictionary <IEnumerable <int>, IEnumerable <int>?>(
                dicOfDicsCapacity, keyComparer
                );

            int keyCounter = 1;

            for (int i = 0; i < dicOfDicsCapacity; ++i)
            {
                var   key     = new List <int>();
                int[] keyData = { keyCounter++, keyCounter++ };
                key.AddRange(keyData);

                List <int>?value = null;
                if (i % 3 != 0)
                {
                    var values = Enumerable.Range(1, i);
                    value = new List <int>(values);
                }

                dicOfDics[key] = value;
            }

            return(dicOfDics);
        }
示例#16
0
        public void RetrieveUserProperties(UserModel user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }
            user.Properties.EnableSync();

            Task.Factory.StartNew(() =>
            {
                user.Properties.Clear();
                var properties    = repository.GetUserProperties(user.Name);
                var models        = properties.Select(p => propertyMapper.GetModel(p));
                var modelComparer = KeyComparer <PropertyModel> .OrderBy(p => p.Name);
                foreach (PropertyModel model in models)
                {
                    int index = user.Properties.ToSublist().UpperBound(model, modelComparer);
                    user.Properties.Insert(index, model);
                }
            }).ContinueWith(
                t => onErrorOccurred(t.Exception),
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnFaulted,
                TaskScheduler.FromCurrentSynchronizationContext()
                );
        }
示例#17
0
        public void CompareExcludeTimestamp()
        {
            var comparer = new KeyComparer(false);
            var x        = new Key();

            Assert.IsFalse(comparer.Equals(x, null));
            Assert.IsFalse(comparer.Equals(null, x));

            var y = new Key();

            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.Row = "A";
            y.Row = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.Row = "AB";
            y.Row = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnFamily = "A";
            y.ColumnFamily = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnFamily = null;
            y.ColumnFamily = string.Empty;
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnFamily = "AB";
            y.ColumnFamily = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnQualifier = "A";
            y.ColumnQualifier = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnQualifier = null;
            y.ColumnQualifier = string.Empty;
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnQualifier = "AB";
            y.ColumnQualifier = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            y.DateTime = new DateTime(2011, 1, 1, 1, 2, 4, DateTimeKind.Utc);
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            y.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));
        }
        public void Search(string searchTerm)
        {
            if (repository == null)
            {
                throw new InvalidOperationException("You must share the connection with the model before searching.");
            }
            if (Group == null)
            {
                throw new InvalidOperationException("You must set the group before searching.");
            }
            if (String.IsNullOrWhiteSpace(searchTerm))
            {
                return;
            }

            if (searchTokenSource != null)
            {
                searchTokenSource.Cancel();
            }
            searchTokenSource = new CancellationTokenSource();

            searchTask = searchTask.ContinueWith(
                t => { IsSearching = true; },
                searchTokenSource.Token,
                TaskContinuationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext()
                ).ContinueWith(t =>
            {
                var searchResults = repository.GetUsers(searchTerm, includeGroups: true);
                return(searchResults);
            }, searchTokenSource.Token).ContinueWith(t =>
            {
                CancellationToken token = searchTokenSource.Token;
                SearchResults.Clear();

                Group group       = repository.GetGroup(Group.Name);
                var searchResults = t.Result;
                var models        = searchResults.Select(m => userMapper.GetMemberModel(group.DistinguishedName, m));
                var modelComparer = KeyComparer <GroupMemberModel> .OrderBy(m => m.FullName).ThenBy(m => m.Name);
                foreach (var model in models)
                {
                    token.ThrowIfCancellationRequested();
                    int index = SearchResults.ToSublist().UpperBound(model, modelComparer);
                    SearchResults.Insert(index, model);
                }
            }, searchTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
            searchTask.ContinueWith(
                t => onErrorOccurred(t.Exception),
                CancellationToken.None,
                TaskContinuationOptions.OnlyOnFaulted,
                TaskScheduler.FromCurrentSynchronizationContext()
                );
            searchTask.ContinueWith(
                t => { IsSearching = false; },
                searchTokenSource.Token,
                TaskContinuationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext()
                );
        }
示例#19
0
        public void WhenFunctionIsProvided_KeyComparerIsCreated()
        {
            //Act
            var comparer = new KeyComparer<TestPoco, int>(f => f.Id);

            //Assert
            Assert.IsNotNull(comparer);
        }
示例#20
0
 public MergeJoinIterator(
     KeyComparer keyComparer,
     IIterator <byte[], byte[]> left, IIterator <byte[], byte[]> right)
 {
     this.keyComparer = keyComparer;
     this.left        = left;
     this.right       = right;
 }
示例#21
0
        public void TestKeyComparer_Explicit_NonGeneric()
        {
            IComparer comparer = KeyComparer <int> .OrderBy(i => i).Untyped();

            int result = comparer.Compare(1, 2);

            Assert.IsTrue(result < 0, "Failed to compare values explicitly.");
        }
示例#22
0
        public void Compare_Nulls()
        {
            var comparer = KeyComparer.Create((City city) => city.Name);

            CompareAssert.IsLessThan(null, athens, comparer);
            CompareAssert.IsEqualTo(null, null, comparer);
            CompareAssert.IsGreaterThan(athens, null, comparer);
        }
示例#23
0
 internal SortedChunkedMap(Func <KeyComparer <TKey>, IMutableSeries <TKey, SortedMap <TKey, TValue> > > outerFactory,
                           Func <int, KeyComparer <TKey>, SortedMap <TKey, TValue> > innerFactory,
                           KeyComparer <TKey> comparer,
                           Opt <int> chunkMaxSize) : base(outerFactory, innerFactory, comparer, chunkMaxSize)
 {
     _chunkUpperLimit = chunkMaxSize.IsPresent && chunkMaxSize.Present > 0 ? chunkMaxSize.Present : Settings.SCMDefaultChunkLength;
     var lastKvp = LastUnchecked;
 }
示例#24
0
        public static int InterpolationLookup <T>(ref T searchSpace, int offset, int length, ref T value, Lookup lookup,
                                                  KeyComparer <T> comparer = default)
        {
            Debug.Assert(length >= 0);

            var i = InterpolationSearch(ref searchSpace, offset, length, value, comparer);

            return(SearchToLookup(offset, length, lookup, i, ref searchSpace, ref value));
        }
                public static KeyComparer For(IEqualityComparer <TKey> comparer)
                {
                    if (comparer != null && !comparer.Equals(EqualityComparer <TKey> .Default))
                    {
                        return(new KeyComparer(comparer));
                    }

                    return(_default ?? (_default = new KeyComparer(EqualityComparer <TKey> .Default)));
                }
示例#26
0
        public void CompareExcludeTimestamp()
        {
            var comparer = new KeyComparer(false);
            var x = new Key();
            Assert.IsFalse(comparer.Equals(x, null));
            Assert.IsFalse(comparer.Equals(null, x));

            var y = new Key();
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.Row = "A";
            y.Row = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.Row = "AB";
            y.Row = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnFamily = "A";
            y.ColumnFamily = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnFamily = null;
            y.ColumnFamily = string.Empty;
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnFamily = "AB";
            y.ColumnFamily = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnQualifier = "A";
            y.ColumnQualifier = "B";
            Assert.IsFalse(comparer.Equals(x, y));

            x.ColumnQualifier = null;
            y.ColumnQualifier = string.Empty;
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.ColumnQualifier = "AB";
            y.ColumnQualifier = "AB";
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            y.DateTime = new DateTime(2011, 1, 1, 1, 2, 4, DateTimeKind.Utc);
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));

            x.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            y.DateTime = new DateTime(2011, 1, 1, 1, 2, 3, DateTimeKind.Utc);
            Assert.IsTrue(comparer.Equals(x, y));
            Assert.AreEqual(comparer.GetHashCode(x), comparer.GetHashCode(y));
        }
示例#27
0
        public long BinarySearch(T value, KeyComparer <T> comparer)
        {
            if (comparer == null)
            {
                comparer = KeyComparer <T> .Default;
            }

            return(BinarySearchUnchecked(0, Length, value, comparer));
        }
        protected virtual bool IsPersistentWithSameIdAs(EntityVersioned <TKey> compareTo)
        {
            if (compareTo == null)
            {
                throw new ArgumentNullException(nameof(compareTo));
            }

            return(!IsTransient && !compareTo.IsTransient && KeyComparer.Equals(Id, compareTo.Id));
        }
示例#29
0
        /// <summary>
        /// Gets the additions and removals from the existing collection.
        /// </summary>
        /// <typeparam name="TValue">The type of the item in the collection</typeparam>
        /// <typeparam name="TKey">The type of the key used for checking if items are in a list</typeparam>
        /// <param name="existingCollection">The existing collection of items.</param>
        /// <param name="latestValues">The latest values to update the collection with</param>
        /// <param name="keyGenerator">A function to generate a key with from a value</param>
        /// <param name="itemsAdded">The items added to the latestValues</param>
        /// <param name="itemsRemoved">The Items removed in the latestValues</param>
        /// <param name="keyComparer">The comparer used for comparing keys</param>
        public static void GetCollectionUpdates <TValue, TKey>(IEnumerable <TValue> existingCollection, IEnumerable <TValue> latestValues,
                                                               Func <TValue, TKey> keyGenerator, out IEnumerable <TValue> itemsAdded, out IEnumerable <TValue> itemsRemoved,
                                                               IEqualityComparer <TKey> keyComparer = null)
        {
            var comparer = new KeyComparer <TValue, TKey>(keyGenerator, keyComparer);

            itemsAdded = latestValues.Except(existingCollection, comparer).ToArray();

            itemsRemoved = existingCollection.Except(latestValues, comparer).ToArray();
        }
示例#30
0
        public static Entities UpdatedEntities(LockSystem preceding, LockSystem present)
        {
            IEqualityComparer <Key> keyComparer = new KeyComparer();
            var updatedKeys = present.Keys.Intersect(preceding.Keys).Except(preceding.Keys.Intersect(present.Keys), keyComparer).Cast <Entity>();
            IEqualityComparer <Lock> lockComparer = new LockComparer();
            var updatedLocks = present.Locks.Intersect(preceding.Locks).Except(preceding.Locks.Intersect(present.Locks), lockComparer).Cast <Entity>();

            //var newPolicies = present.Policies.Except(preceding.Policies).Cast<Entity>();
            return(updatedKeys.Concat(updatedLocks).ToList());
        }
        public ImmutableSortedDictionary(IComparer <TKey> keyComparer)
        {
            if (keyComparer == null)
            {
                throw new ArgumentNullException(nameof(keyComparer));
            }

            _root     = EmptyTwoThree <KeyValuePair <TKey, TValue> > .Instance;
            _comparer = new KeyComparer <TKey, TValue>(keyComparer);
        }
示例#32
0
        public ImmutableRedBlackDictionary(IComparer <TKey> keyComparer)
        {
            if (keyComparer == null)
            {
                throw new ArgumentNullException(nameof(keyComparer));
            }

            _root     = RedBlackLeaf <KeyValuePair <TKey, TValue> > .Instance;
            _comparer = new KeyComparer <TKey, TValue>(keyComparer);
        }
示例#33
0
        public void WhenDataGiven_ShouldReturnHashCodeOfProperty()
        {
            //Arrange
            var comparer = new KeyComparer<TestPoco, int>(f => f.Id) as IEqualityComparer<TestPoco>;
            var data = new TestPoco() { Id = 1 };

            //Act
            var result = comparer.GetHashCode(data);

            //Assert
            Assert.AreEqual(data.Id.GetHashCode(), result);
        }
示例#34
0
        public void WhenPropertiesComparedAreNotEqual_ShouldReturnFalse()
        {
            //Arrange
            var comparer = new KeyComparer<TestPoco, int>(f => f.Id) as IEqualityComparer<TestPoco>;
            var one = new TestPoco() { Id = 1 };
            var two = new TestPoco() { Id = 2 };

            //Act
            var result = comparer.Equals(one, two);

            //Assert
            Assert.IsFalse(result);
        }
示例#35
0
        public void ScanTableRandomCells()
        {
            var random = new Random();
            const string Cf = "abcdefg";
            const int Count = 10000;
            using (var _table = EnsureTable("ScanTableRandomCells", Schema)) {
                var keys = new List<Key>(Count);
                using (var mutator = _table.CreateMutator()) {
                    for (var i = 0; i < Count; ++i) {
                        var key = new Key
                            {
                                Row = Guid.NewGuid().ToString(),
                                ColumnFamily = new string(new[] { Cf[random.Next(Cf.Length)] }),
                                ColumnQualifier = random.Next(Cf.Length).ToString(CultureInfo.InvariantCulture)
                            };
                        keys.Add(key);
                        mutator.Set(key, Encoding.GetBytes(key.Row));
                    }
                }

                for (var r = 0; r < 10; ++r) {
                    var countCells = 10 + random.Next(Count - 10);
                    var scanSpec = new ScanSpec();
                    foreach (var k in Shuffle(keys)) {
                        scanSpec.AddCell(k);
                        if (scanSpec.CellCount == countCells) {
                            break;
                        }
                    }

                    var comparer = new KeyComparer(false);
                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            Assert.IsTrue(comparer.Equals(scanSpec.Cells[c++], cell.Key));
                        }

                        Assert.AreEqual(scanSpec.CellCount, c);
                    }
                }

                for (var r = 0; r < 10; ++r) {
                    var countCells = 10 + random.Next(Count - 10);
                    var scanSpec = new ScanSpec();
                    foreach (var k in Shuffle(keys)) {
                        scanSpec.AddRow(k.Row);
                        if (scanSpec.RowCount == countCells) {
                            break;
                        }
                    }

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            Assert.AreEqual(scanSpec.Rows[c++], cell.Key.Row);
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }
                }

                for (var r = 0; r < 10; ++r) {
                    var rows = new HashSet<string>();
                    var countCells = 10 + random.Next(Count - 10);
                    var scanSpec = new ScanSpec(true);
                    foreach (var k in Shuffle(keys)) {
                        scanSpec.AddRow(k.Row);
                        rows.Add(k.Row);
                        if (scanSpec.RowCount == countCells) {
                            break;
                        }
                    }

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            Assert.IsTrue(rows.Contains(cell.Key.Row));
                            ++c;
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }
                }

                for (var r = 0; r < 10; ++r) {
                    var rows = new HashSet<string>();
                    var columnFamily = new string(new[] { Cf[random.Next(Cf.Length)] });
                    var columnQualifier = random.Next(Cf.Length).ToString(CultureInfo.InvariantCulture);
                    var countCells = 10 + random.Next(Count / 10);
                    var scanSpec = new ScanSpec { ScanAndFilter = true };
                    foreach (var k in Shuffle(keys).Where(k => k.ColumnFamily == columnFamily && k.ColumnQualifier == columnQualifier)) {
                        Assert.AreEqual(columnFamily, k.ColumnFamily);
                        Assert.AreEqual(columnQualifier, k.ColumnQualifier);
                        scanSpec.AddColumn(k.ColumnFamily + ":" + k.ColumnQualifier);
                        scanSpec.AddRow(k.Row);
                        rows.Add(k.Row);
                        if (scanSpec.RowCount == countCells) {
                            break;
                        }
                    }

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            Assert.AreEqual(columnFamily, cell.Key.ColumnFamily);
                            Assert.AreEqual(columnQualifier, cell.Key.ColumnQualifier);
                            Assert.IsTrue(rows.Contains(cell.Key.Row));
                            ++c;
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }
                }

                for (var r = 0; r < 10; ++r) {
                    var rows = new HashSet<string>();
                    var columnQualifier = random.Next(Cf.Length).ToString(CultureInfo.InvariantCulture);
                    var countCells = 10 + random.Next(Count / 10);
                    var scanSpec = new ScanSpec { ScanAndFilter = true };
                    foreach (var k in Shuffle(keys).Where(k => k.ColumnQualifier == columnQualifier)) {
                        Assert.AreEqual(columnQualifier, k.ColumnQualifier);
                        scanSpec.AddColumn(k.ColumnFamily + ":" + k.ColumnQualifier);
                        scanSpec.AddRow(k.Row);
                        rows.Add(k.Row);
                        if (scanSpec.RowCount == countCells) {
                            break;
                        }
                    }

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            Assert.AreEqual(columnQualifier, cell.Key.ColumnQualifier);
                            Assert.IsTrue(rows.Contains(cell.Key.Row));
                            ++c;
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }
                }

                using (var mutator = _table.CreateMutator()) {
                    var key = new Key { Row = "A", ColumnFamily = "a", ColumnQualifier = "1" };
                    mutator.Set(key, Encoding.GetBytes(key.Row));

                    key = new Key { Row = "B", ColumnFamily = "a", ColumnQualifier = "2" };
                    mutator.Set(key, Encoding.GetBytes(key.Row));

                    key = new Key { Row = "C", ColumnFamily = "c", ColumnQualifier = "3" };
                    mutator.Set(key, Encoding.GetBytes(key.Row));

                    key = new Key { Row = "D", ColumnFamily = "c", ColumnQualifier = "4" };
                    mutator.Set(key, Encoding.GetBytes(key.Row));

                    key = new Key { Row = "E", ColumnFamily = "b", ColumnQualifier = "5" };
                    mutator.Set(key, Encoding.GetBytes(key.Row));
                }

                {
                    var scanSpec = new ScanSpec { ScanAndFilter = true };
                    scanSpec.AddColumn("a:1");
                    scanSpec.AddColumn("a:2");
                    scanSpec.AddColumn("b:5");
                    scanSpec.AddColumn("c:3");
                    scanSpec.AddColumn("c:4");
                    scanSpec.AddRow("A");
                    scanSpec.AddRow("B");

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            ++c;
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }

                    scanSpec = new ScanSpec { ScanAndFilter = true };
                    scanSpec.AddColumn("a", "b:5", "c");
                    scanSpec.AddRow("A");
                    scanSpec.AddRow("C");
                    scanSpec.AddRow("E");

                    using (var scanner = _table.CreateScanner(scanSpec)) {
                        Assert.AreSame(scanSpec, scanner.ScanSpec);
                        var cell = new Cell();
                        var c = 0;
                        while( scanner.Move(cell) ) {
                            Assert.AreEqual(cell.Key.Row, Encoding.GetString(cell.Value));
                            ++c;
                        }

                        Assert.AreEqual(scanSpec.RowCount, c);
                    }
                }
            }
        }