public async Task Confirmation_token_cant_be_used_twice_by_different_owners_for_the_same_resource()
        {
            var reservationService = new SqlReservationService();

            // given a fixed quantity of some resource where the resource has been used
            var word              = Any.Word();
            var ownerToken        = Any.Guid().ToString();
            var promoCode         = "promo-code-" + word;
            var reservedValue     = Any.Guid().ToString();
            var confirmationToken = Any.Guid().ToString();
            await reservationService.Reserve(reservedValue, promoCode, reservedValue, TimeSpan.FromDays(-1));

            await reservationService.Reserve(Any.Guid().ToString(), promoCode, reservedValue, TimeSpan.FromDays(-1));

            //act
            await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                confirmationToken : confirmationToken);

            //assert
            Action reserve = () =>
            {
                var result = reservationService.ReserveAny(
                    scope: promoCode,
                    ownerToken: Any.FullName(),
                    lease: TimeSpan.FromMinutes(2), confirmationToken: confirmationToken)
                             .Result;
            };

            reserve.ShouldThrow <DbUpdateException>();
        }
        public async Task When_confirmation_token_is_used_twice_for_the_same_unconfirmed_reservation_then_ReserveAny_extends_the_lease()
        {
            var reservationService = new SqlReservationService();

            // given a fixed quantity of some resource where the resource has been used
            //todo:(this needs to be done via an interface rather then just calling reserve multiple times)
            var word              = Any.Word();
            var ownerToken        = Any.Guid().ToString();
            var promoCode         = "promo-code-" + word;
            var reservedValue     = Any.Guid().ToString();
            var confirmationToken = Any.Guid().ToString();
            await reservationService.Reserve(reservedValue, promoCode, reservedValue, TimeSpan.FromDays(-1));

            await reservationService.Reserve(Any.Guid().ToString(), promoCode, reservedValue, TimeSpan.FromDays(-1));

            //act
            var firstAttempt = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                confirmationToken : confirmationToken);

            //assert
            var secondAttempt = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                lease : TimeSpan.FromMinutes(2),
                confirmationToken : confirmationToken);

            secondAttempt.Should()
            .NotBeNull()
            .And
            .Be(firstAttempt);
        }
        public async Task If_a_fixed_quantity_of_resource_had_been_depleted_then_reservations_cant_be_made()
        {
            var reservationService = new SqlReservationService();

            // given a fixed quantity of some resource where the resource has been used
            var word                 = Any.Word();
            var ownerToken           = Any.Guid().ToString();
            var promoCode            = "promo-code-" + word;
            var reservedValue        = Any.Guid().ToString();
            var userConfirmationCode = Any.Guid().ToString();
            await reservationService.Reserve(reservedValue, promoCode, reservedValue, TimeSpan.FromDays(-1));

            //act
            var result = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                lease : TimeSpan.FromMinutes(-2), confirmationToken : userConfirmationCode);

            result.Should().Be(reservedValue);
            await reservationService.Confirm(userConfirmationCode, promoCode, ownerToken);

            //assert
            result = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : Any.FullName(),
                lease : TimeSpan.FromMinutes(2), confirmationToken : Any.Guid().ToString());

            result.Should().BeNull();
        }
        public async Task The_value_returned_by_the_reservation_service_can_be_used_for_confirmation()
        {
            var reservationService = new SqlReservationService();

            // given a fixed quantity of some resource, e.g. promo codes:
            var ownerToken    = "owner-token-" + Any.Email();
            var promoCode     = "promo-code-" + Any.Word();
            var reservedValue = Any.Email();
            await reservationService.Reserve(reservedValue,
                                             scope : promoCode,
                                             ownerToken : ownerToken,
                                             lease : TimeSpan.FromDays(-1));

            //act
            var value = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                lease : TimeSpan.FromMinutes(2));

            value.Should().NotBeNull();

            await reservationService.Confirm(value, promoCode, ownerToken);

            // assert
            using (var db = new ReservationServiceDbContext())
            {
                var reservation = db.Set <ReservedValue>()
                                  .Single(v => v.Value == reservedValue &&
                                          v.Scope == promoCode &&
                                          v.Expiration == null);
                reservation.ConfirmationToken.Should().Be(value);
            }
        }
        public async Task Reservations_can_be_placed_for_one_of_a_fixed_quantity_of_a_resource()
        {
            var reservationService = new SqlReservationService();

            // given a fixed quantity of some resource, e.g. promo codes:
            var word                 = Any.Word();
            var ownerToken           = Any.Guid().ToString();
            var promoCode            = "promo-code-" + word;
            var reservedValue        = Any.Guid().ToString();
            var userConfirmationCode = Any.Guid().ToString();
            await reservationService.Reserve(reservedValue, promoCode, reservedValue, TimeSpan.FromDays(-1));

            //act
            var result = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : ownerToken,
                lease : TimeSpan.FromMinutes(2), confirmationToken : userConfirmationCode);

            result.Should().Be(reservedValue);

            await reservationService.Confirm(userConfirmationCode, promoCode, ownerToken);

            // assert
            using (var db = new ReservationServiceDbContext())
            {
                db.Set <ReservedValue>()
                .Should().Contain(v => v.Value == reservedValue &&
                                  v.Scope == promoCode &&
                                  v.Expiration == null);
            }
        }
        public async Task When_simultaneous_reservations_are_placed_for_one_of_a_fixed_quantity_of_a_resource_then_different_values_are_reserved()
        {
            //arrange
            var barrier = new Barrier(2);

            var reservationService = new SqlReservationService(() => new ReservationServiceDbContextThatForcesConcurrencyDuringSave(barrier));

            // given a fixed quantity of some resource, e.g. promo codes:
            var promoCode = "promo-code-" + Any.Word();
            var reservedValue1 = "firstValue:" + Any.CamelCaseName();
            var reservedValue2 = "SecondValue:" + Any.CamelCaseName();
            await reservationService.Reserve(reservedValue1, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));
            await reservationService.Reserve(reservedValue2, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));

            //act
            var result = await reservationService.ReserveAny(
                scope: promoCode,
                ownerToken: Any.FullName(),
                lease: TimeSpan.FromMinutes(2),
                confirmationToken: Any.CamelCaseName());

            var result2 = await reservationService.ReserveAny(
                scope: promoCode,
                ownerToken: Any.FullName(),
                lease: TimeSpan.FromMinutes(2),
                confirmationToken: Any.CamelCaseName());

            //assert
            result.Should().NotBe(result2);
        }
Esempio n. 7
0
        public async Task When_simultaneous_reservations_are_placed_for_one_of_a_fixed_quantity_of_a_resource_then_different_values_are_reserved()
        {
            //arrange
            var barrier = new Barrier(2);

            var reservationService = new SqlReservationService(() => new ReservationServiceDbContextThatForcesConcurrencyDuringSave(barrier));

            // given a fixed quantity of some resource, e.g. promo codes:
            var promoCode      = "promo-code-" + Any.Word();
            var reservedValue1 = "firstValue:" + Any.CamelCaseName();
            var reservedValue2 = "SecondValue:" + Any.CamelCaseName();
            await reservationService.Reserve(reservedValue1, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));

            await reservationService.Reserve(reservedValue2, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));

            //act
            var result = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : Any.FullName(),
                lease : TimeSpan.FromMinutes(2),
                confirmationToken : Any.CamelCaseName());

            var result2 = await reservationService.ReserveAny(
                scope : promoCode,
                ownerToken : Any.FullName(),
                lease : TimeSpan.FromMinutes(2),
                confirmationToken : Any.CamelCaseName());

            //assert
            result.Should().NotBe(result2);
        }
        public async Task When_ReserveAny_is_called_for_a_scope_that_has_no_entries_at_all_then_it_returns_false()
        {
            var reservationService = new SqlReservationService();

            var value = await reservationService.ReserveAny(Any.CamelCaseName(), Any.CamelCaseName(), TimeSpan.FromMinutes(1));

            value.Should().BeNull();
        }
Esempio n. 9
0
        public async Task When_simultaneous_reservations_are_placed_for_one_of_a_fixed_quantity_of_a_resource_then_different_values_are_reserved()
        {
            //arrange
            var reservationService1 = new SqlReservationService();
            var reservationService2 = new SqlReservationService();

            // given a fixed quantity of some resource, e.g. promo codes:
            var promoCode      = "promo-code-" + Any.Word();
            var reservedValue1 = "firstValue:" + Any.Guid();
            var reservedValue2 = "SecondValue:" + Any.Guid();
            await reservationService1.Reserve(reservedValue1, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));

            await reservationService2.Reserve(reservedValue2, promoCode, Any.CamelCaseName(), TimeSpan.FromDays(-1));

            //Both services retrieve the same entry on the first reservation attempt
            //A subsequent call will give a different entry
            var db1 = new ReservationServiceDbContext();
            var db2 = new ReservationServiceDbContext();

            reservationService1.CreateReservationServiceDbContext = () => db1;
            reservationService2.CreateReservationServiceDbContext = () => db2;

            var entry1  = db1.ReservedValues.Single(r => r.Value == reservedValue1);
            var entry_1 = db2.ReservedValues.Single(r => r.Value == reservedValue1);
            var entry2  = db2.ReservedValues.Single(r => r.Value == reservedValue2);

            var queue = new Queue <ReservedValue>(new[]
            {
                entry_1,
                entry2
            });

            reservationService1.GetValueToReserve = (reservedValues, scope, now) => Task.FromResult(entry1);
            reservationService2.GetValueToReserve = (reservedValues, scope, now) => Task.FromResult(queue.Dequeue());

            //act
            var result = await reservationService1.ReserveAny(
                scope : promoCode,
                ownerToken : Any.FullName(),
                lease : TimeSpan.FromMinutes(2),
                confirmationToken : Any.CamelCaseName());

            var result2 = await reservationService2.ReserveAny(
                scope : promoCode,
                ownerToken : Any.FullName(),
                lease : TimeSpan.FromMinutes(2),
                confirmationToken : Any.CamelCaseName());

            //assert
            result.Should().NotBe(result2);
        }