/// <summary>
        /// A very naive version of property-based testing API.
        /// </summary>
        /// <remarks>
        /// This implementation may be moved to a proper property-based testing framework like FsCheck.
        /// </remarks>
        private static void TestProperty(Func <MachineId[], MachineIdCollection, bool> propertyChecker, [CallerMemberName] string operation = null)
        {
            const ushort maxMachineId = 2048;
            const int    count        = 50;
            var          random       = new Random();

            // Explicitly validating the property for empty collection and the collection with 1 element.
            validateProperty(0);
            validateProperty(1);

            for (int i = 0; i < count; i++)
            {
                var collectionLength = random.Next(count);
                validateProperty(collectionLength);
            }

            void validateProperty(int collectionLength)
            {
                var arrayOfMachineIds = Enumerable.Range(1, collectionLength).Select(_ => new MachineId(random.Next(maxMachineId))).ToArray();

                var machineIdCollection = arrayOfMachineIds.Length == 1 ? MachineIdCollection.Create(arrayOfMachineIds[0]) : MachineIdCollection.Create(arrayOfMachineIds);

                Assert.True(propertyChecker(arrayOfMachineIds, machineIdCollection), $"The property '{operation}' is falsifiable.");
            }
        }
Esempio n. 2
0
        public void BinManagerExcludesMaster()
        {
            var amountMachines  = 4;
            var machineMappings = Enumerable.Range(0, amountMachines).Select(i => new MachineMapping(new MachineLocation(i.ToString()), new MachineId(i))).ToArray();
            var masterMapping   = machineMappings[0];

            var clusterState = new ClusterState(machineMappings[0].Id, machineMappings)
            {
                EnableBinManagerUpdates = true
            };

            foreach (var mapping in machineMappings)
            {
                clusterState.AddMachine(mapping.Id, mapping.Location);
            }

            clusterState.SetMasterMachine(masterMapping.Location);
            clusterState.InitializeBinManagerIfNeeded(locationsPerBin: amountMachines, _clock, expiryTime: TimeSpan.Zero);

            var binMappings = clusterState.GetBinMappings().ThrowIfFailure();

            foreach (var binMapping in binMappings)
            {
                // Master should not be there
                binMapping.Length.Should().Be(amountMachines - 1);
                binMapping.Should().NotContain(masterMapping.Id);
            }

            // Make sure this stays true after updates
            var inactiveMachines = new BitMachineIdSet(new byte[amountMachines], 0);

            inactiveMachines = inactiveMachines.SetExistenceBits(MachineIdCollection.Create(machineMappings[1].Id), true);
            clusterState.SetMachineStates(inactiveMachines).ShouldBeSuccess();

            binMappings = clusterState.GetBinMappings().ThrowIfFailure();
            foreach (var binMapping in binMappings)
            {
                // Master and inactive should not be there
                binMapping.Length.Should().Be(amountMachines - 2);
                binMapping.Should().NotContain(masterMapping.Id);
            }
        }