Exemple #1
0
        public void ViaCacheRoundtrip()
        {
            var guid        = CacheDeterminism.NewCacheGuid();
            var determinism = CacheDeterminism.ViaCache(guid, DateTime.MaxValue);

            Assert.Equal(guid, determinism.EffectiveGuid);
        }
Exemple #2
0
        public void ContentHashListWithDeterminismProperty()
        {
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(
                ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires));

            Assert.Equal(contentHashListWithDeterminism, new GetContentHashListResult(contentHashListWithDeterminism).ContentHashListWithDeterminism);
        }
Exemple #3
0
        public void EqualsFalseContentHashListMismatch()
        {
            var determinism = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires);
            var v1          = new GetContentHashListResult(new ContentHashListWithDeterminism(ContentHashList.Random(), determinism));
            var v2          = new GetContentHashListResult(new ContentHashListWithDeterminism(ContentHashList.Random(), determinism));

            Assert.False(v1.Equals(v2));
        }
Exemple #4
0
        public void GetHashCodeNotSameWhenNotEqual()
        {
            var v1 = new GetContentHashListResult(new ContentHashListWithDeterminism(
                                                      ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires)));
            var v2 = new GetContentHashListResult(new ContentHashListWithDeterminism(
                                                      ContentHashList.Random(), CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires)));

            Assert.NotEqual(v1.GetHashCode(), v2.GetHashCode());
        }
Exemple #5
0
        public void EqualsFalseDeterminismMismatch()
        {
            var v1 = new AddOrGetContentHashListResult(
                new ContentHashListWithDeterminism(null, CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.MaxValue)));
            var v2 = new AddOrGetContentHashListResult(
                new ContentHashListWithDeterminism(null, CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.MaxValue)));

            Assert.False(v1.Equals(v2));
        }
        public async Task Roundtrip()
        {
            var fileName = $"{Guid.NewGuid()}.json";

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var sessionId        = 42;
                var serializedConfig = "Foo";
                var pat = Guid.NewGuid().ToString();

                var numOperations = 3;
                var operations    = Enumerable.Range(0, numOperations)
                                    .Select(_ => generateRandomOperation())
                                    .ToList();

                var sessionInfo = new HibernatedCacheSessionInfo(sessionId, serializedConfig, pat, operations);
                var sessions1   = new HibernatedSessions <HibernatedCacheSessionInfo>(new List <HibernatedCacheSessionInfo> {
                    sessionInfo
                });
                await sessions1.WriteAsync(FileSystem, directory.Path, fileName);

                FileSystem.HibernatedSessionsExists(directory.Path, fileName).Should().BeTrue();

                var fileSize = FileSystem.GetFileSize(directory.Path / fileName);
                fileSize.Should().BeGreaterThan(0);

                var sessions2 = await FileSystem.ReadHibernatedSessionsAsync <HibernatedCacheSessionInfo>(directory.Path, fileName);

                sessions2.Sessions.Count.Should().Be(1);
                sessions2.Sessions[0].Id.Should().Be(sessionId);
                sessions2.Sessions[0].SerializedSessionConfiguration.Should().Be(serializedConfig);
                sessions2.Sessions[0].Pat.Should().Be(pat);
                sessions2.Sessions[0].PendingPublishingOperations.Should().BeEquivalentTo(operations);

                await FileSystem.DeleteHibernatedSessions(directory.Path, fileName);

                PublishingOperation generateRandomOperation()
                {
                    var amountOfHashes  = 3;
                    var hashes          = Enumerable.Range(0, amountOfHashes).Select(_ => ContentHash.Random()).ToArray();
                    var contentHashList = new ContentHashList(hashes);
                    var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow.AddMilliseconds(ThreadSafeRandom.Generator.Next()));
                    var contentHashListWithDeterminism = new ContentHashListWithDeterminism(contentHashList, determinism);

                    var fingerprint       = new Fingerprint(ContentHash.Random().ToByteArray());
                    var selector          = new Selector(ContentHash.Random());
                    var strongFingerprint = new StrongFingerprint(fingerprint, selector);

                    return(new PublishingOperation
                    {
                        ContentHashListWithDeterminism = contentHashListWithDeterminism,
                        StrongFingerprint = strongFingerprint
                    });
                }
            }
        }
Exemple #7
0
        public void EqualsTrueNotReferenceEqualContentHashList()
        {
            var contentHashList = ContentHashList.Random();
            var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires);
            var contentHashListWithDeterminism1 = new ContentHashListWithDeterminism(contentHashList, determinism);
            var contentHashListWithDeterminism2 = new ContentHashListWithDeterminism(contentHashList, determinism);
            var v1 = new GetContentHashListResult(contentHashListWithDeterminism1);
            var v2 = new GetContentHashListResult(contentHashListWithDeterminism2);

            Assert.True(v1.Equals(v2));
        }
Exemple #8
0
        public async Task DisconnectMostRemoteCacheAddNewReconnect()
        {
            string cacheId   = "MutlipleCacheRemote";
            ICache testCache = await InitializeCacheAsync(NewCache(cacheId, true, false, true)).SuccessAsync();

            VerticalCacheAggregator lowerVert = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(lowerVert);

            CallbackCacheWrapper callbackCache = lowerVert.RemoteCache as CallbackCacheWrapper;

            XAssert.IsNotNull(callbackCache);

            VerticalCacheAggregator upperVert = callbackCache.WrappedCache as VerticalCacheAggregator;

            XAssert.IsNotNull(upperVert);

            ICacheSession session = await testCache.CreateSessionAsync().SuccessAsync();

            VerticalAggregatorDisconnectTests.DisconnectCache(upperVert.RemoteCache);

            FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "Test Pip");

            VerticalAggregatorDisconnectTests.ConnectCache(upperVert.RemoteCache);

            // Now query each cache, and verify only the remote content is in each.
            var aggregatorStats   = new Dictionary <string, double>();
            var remoteDeterminism = CacheDeterminism.ViaCache(upperVert.RemoteCache.CacheGuid, CacheDeterminism.NeverExpires);

            foreach (var currentCache in new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >[]
            {
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(testCache, remoteDeterminism, lowerVert.LocalCache.CacheId, 3, aggregatorStats),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(lowerVert.LocalCache, remoteDeterminism, lowerVert.LocalCache.CacheId, 1, null),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(upperVert.LocalCache, remoteDeterminism, upperVert.LocalCache.CacheId, 1, null),
                new Tuple <ICache, CacheDeterminism, string, int, Dictionary <string, double> >(upperVert.RemoteCache, remoteDeterminism, upperVert.RemoteCache.CacheId, 1, null)
            })
            {
                await ValidateItemsInCacheAsync(
                    currentCache.Item1,
                    cacheRecord.StrongFingerprint.WeakFingerprint,
                    new List <CasHash>(cacheRecord.CasEntries),
                    currentCache.Item2,
                    cacheRecord.StrongFingerprint.CasElement,
                    currentCache.Item3,
                    currentCache.Item4);
            }

            await testCache.ShutdownAsync().SuccessAsync();
        }
Exemple #9
0
        public Task AddOrGetContentHashListPassThrough()
        {
            var context           = new Context(Logger);
            var strongFingerprint = StrongFingerprint.Random();
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(
                ContentHashList.Random(),
                CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires));

            return(RunMockSessionTestAsync(context, session =>
            {
                session.AddOrGetContentHashListAsync(context, strongFingerprint, contentHashListWithDeterminism, Token, NonDefaultUrgencyHint).ConfigureAwait(false).GetAwaiter().GetResult().ShouldBeSuccess();
                Assert.True(_mockMemoizationSession.AddOrGetContentHashListAsyncParams.Contains(new Tuple <StrongFingerprint, ContentHashListWithDeterminism>(strongFingerprint, contentHashListWithDeterminism)));
                return Task.FromResult(0);
            }));
        }
Exemple #10
0
        public Task AddExpiredDeterminism()
        {
            var strongFingerprint = StrongFingerprint.Random();
            var expirationUtc     = DateTime.UtcNow - TimeSpan.FromDays(7);
            var guid        = CacheDeterminism.NewCacheGuid();
            var determinism = CacheDeterminism.ViaCache(guid, expirationUtc);
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(ContentHashList.Random(), determinism);

            return(RunTest((context, contentLocationDatabase) =>
            {
                contentLocationDatabase.AddOrGetContentHashList(
                    context, strongFingerprint, contentHashListWithDeterminism).ShouldBeSuccess();
                var result = contentLocationDatabase.GetContentHashList(context, strongFingerprint);
                Assert.Equal(CacheDeterminism.None.EffectiveGuid, result.ContentHashListWithDeterminism.Determinism.EffectiveGuid);
            }));
        }
        /// <summary>
        ///     Determine the Determinism to return.
        /// </summary>
        protected static CacheDeterminism UnpackDeterminism(ContentHashListWithCacheMetadata cacheMetadata, Guid cacheId)
        {
            Contract.Assert(cacheMetadata != null);

            if (cacheMetadata.ContentHashListWithDeterminism.Determinism.Guid == CacheDeterminism.Tool.Guid)
            {
                // Value is Tool-deterministic
                return(CacheDeterminism.Tool);
            }

            var expirationUtc = cacheMetadata.GetEffectiveExpirationTimeUtc();

            return(expirationUtc == null
                ? CacheDeterminism.None                                     // Value is unbacked in VSTS
                : CacheDeterminism.ViaCache(cacheId, expirationUtc.Value)); // Value is backed in VSTS
        }
        public Task AddExpiredDeterminism()
        {
            var context           = new Context(Logger);
            var strongFingerprint = StrongFingerprint.Random();
            var expirationUtc     = DateTime.UtcNow - TimeSpan.FromDays(7);
            var guid        = CacheDeterminism.NewCacheGuid();
            var determinism = CacheDeterminism.ViaCache(guid, expirationUtc);
            var contentHashListWithDeterminism = new ContentHashListWithDeterminism(ContentHashList.Random(), determinism);

            return(RunTestAsync(context, async session =>
            {
                await session.AddOrGetContentHashListAsync(
                    context, strongFingerprint, contentHashListWithDeterminism, Token).ShouldBeSuccess();
                var result = await session.GetContentHashListAsync(context, strongFingerprint, Token);
                Assert.Equal(CacheDeterminism.None.EffectiveGuid, result.ContentHashListWithDeterminism.Determinism.EffectiveGuid);
            }));
        }
Exemple #13
0
        public void ContentHashListWithDeterminismToRedisValue()
        {
            var chl        = ContentHashList.Random();
            var d          = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow);
            var chlwd      = new ContentHashListWithDeterminism(chl, d);
            var redisValue = _serializer.ToRedisValue(chlwd);
            var expected   =
                HexUtilities.BytesToHex(d.Serialize()) +
                RedisSerializer.RedisValueSeparator +
                RedisSerializer.RedisValueExistsSemaphore +
                RedisSerializer.RedisValueSeparator +
                chl.Serialize() +
                RedisSerializer.RedisValueSeparator +
                RedisSerializer.RedisValueSeparator;

            Assert.Equal(expected, redisValue);
        }
Exemple #14
0
        /// <inheritdoc />
        public override object ReadJson(
            JsonReader reader,
            Type objectType,
            object existingValue,
            JsonSerializer serializer)
        {
            JObject jsonObject = JObject.Load(reader);

            byte[] payload = null;
            JToken payloadValue;

            if (jsonObject.TryGetValue(PayloadFieldName, StringComparison.Ordinal, out payloadValue))
            {
                payload = HexUtilities.HexToBytes(payloadValue.Value <string>());
            }

            JToken expirationUtcToken;
            var    expirationUtc = jsonObject.TryGetValue(ExpirationUtcFieldName, StringComparison.Ordinal, out expirationUtcToken)
                ? DateTime.FromBinary(expirationUtcToken.Value <long>())
                : CacheDeterminism.Expired;
            CacheDeterminism determinism =
                CacheDeterminism.ViaCache(
                    Guid.Parse(jsonObject.GetValue(DeterminismFieldName, StringComparison.Ordinal).Value <string>()),
                    expirationUtc);

            var contentHashes = new List <ContentHash>();

            foreach (
                string contentHashString in jsonObject.GetValue(HashesFieldName, StringComparison.Ordinal).Values <string>())
            {
                ContentHash deserializedContentHash;
                if (!ContentHash.TryParse(contentHashString, out deserializedContentHash))
                {
                    throw new InvalidDataException("Unable to parse hash out of JSON Token");
                }

                contentHashes.Add(deserializedContentHash);
            }

            var contentHashList = new ContentHashList(contentHashes.ToArray(), payload);

            return(new ContentHashListWithDeterminism(contentHashList, determinism));
        }
        public async Task SinglePhaseNonDeterministic()
        {
            const string TestName    = nameof(SinglePhaseNonDeterministic);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

            // Now for the session (which we base on the cache ID)
            string        testSessionId = "Session1-" + testCacheId;
            ICacheSession session       = await CreateSessionAsync(cache, testSessionId);

            PipDefinition[] pips =
            {
                new PipDefinition("PipA", determinism: CacheDeterminism.SinglePhaseNonDeterministic),
                new PipDefinition("PipB", determinism: CacheDeterminism.SinglePhaseNonDeterministic)
            };

            FullCacheRecord[] records = (await pips.BuildAsync(session)).ToArray();
            XAssert.AreEqual(2, records.Length);

            // Now, we should be able to redo those adds but swap the CasEntries in the records
            // and get them replaced
            for (int i = 0; i < 2; i++)
            {
                // Make sure we have our own strong fingerprint (no cheating by the cache for this one)
                var strong = records[i].StrongFingerprint;
                strong = new StrongFingerprint(strong.WeakFingerprint, strong.CasElement, strong.HashElement, "testing");

                // Validate that the GetCacheEntry produces what we expect
                var entries = await session.GetCacheEntryAsync(strong).SuccessAsync();

                XAssert.AreEqual(records[i].CasEntries, entries);

                // Validate that the other record I am going to do is different
                var other = records[1 - i].CasEntries;
                XAssert.AreNotEqual(entries, other, "Other record must be different!");

                var newRecord = await session.AddOrGetAsync(strong.WeakFingerprint, strong.CasElement, strong.HashElement, other).SuccessAsync();

                XAssert.IsNull(newRecord.Record, "Should have replaced");

                entries = await session.GetCacheEntryAsync(strong).SuccessAsync();

                XAssert.AreEqual(other, entries);
                XAssert.AreNotEqual(records[i].CasEntries, entries);

                // Try to replace the existing SinglePhaseNonDeterministic case with a recird that is deterministic with a cache
                var fail = await session.AddOrGetAsync(strong.WeakFingerprint, strong.CasElement, strong.HashElement, new CasEntries(records[i].CasEntries, CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), CacheDeterminism.NeverExpires)));

                XAssert.IsFalse(fail.Succeeded, "Should have failed trying to replace SinglePhaseNonDeterministic with cache deterministic");
                XAssert.AreEqual(typeof(SinglePhaseMixingFailure), fail.Failure.GetType());

                // Try to replace the existing SinglePhaseNonDeterministic case with a recird that is deterministic tool
                fail = await session.AddOrGetAsync(strong.WeakFingerprint, strong.CasElement, strong.HashElement, new CasEntries(records[i].CasEntries, CacheDeterminism.Tool));

                XAssert.IsFalse(fail.Succeeded, "Should have failed trying to replace SinglePhaseNonDeterministic with tool deterministic");
                XAssert.AreEqual(typeof(SinglePhaseMixingFailure), fail.Failure.GetType());

                // Try to replace the existing SinglePhaseNonDeterministic case with a recird that is not deterministic
                fail = await session.AddOrGetAsync(strong.WeakFingerprint, strong.CasElement, strong.HashElement, new CasEntries(records[i].CasEntries, CacheDeterminism.None));

                XAssert.IsFalse(fail.Succeeded, "Should have failed trying to replace SinglePhaseNonDeterministic with non-deterministic");
                XAssert.AreEqual(typeof(SinglePhaseMixingFailure), fail.Failure.GetType());
            }

            await CloseSessionAsync(session, testSessionId);
            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #16
0
 private static CacheDeterminism RandomCacheDeterminism()
 {
     return(CacheDeterminism.ViaCache(Guid.NewGuid(), DateTime.UtcNow));
 }
        public async Task CacheSessionDataIsHibernated()
        {
            using var testDirectory = new DisposableDirectory(FileSystem);
            var cacheDirectory  = testDirectory.Path / "Service";
            var cacheName       = "theCache";
            var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                [cacheName] = cacheDirectory / "Root"
            };
            var grpcPort            = PortExtensions.GetNextAvailablePort();
            var serverConfiguration = new LocalServerConfiguration(cacheDirectory, namedCacheRoots, grpcPort, FileSystem)
            {
                GrpcPortFileName = null, // Port is well known at configuration time, no need to expose it.
            };
            var scenario = "Default";

            var server = new LocalCacheServer(
                FileSystem,
                TestGlobal.Logger,
                scenario,
                cacheFactory: CreateBlockingPublishingCache,
                serverConfiguration,
                Capabilities.All);

            var context = new OperationContext(new Context(Logger));
            await server.StartupAsync(context).ShouldBeSuccess();

            var pat = Guid.NewGuid().ToString();
            var publishingConfig = new PublishingConfigDummy
            {
                PublishAsynchronously = true,
            };

            using var clientCache = CreateClientCache(publishingConfig, pat, cacheName, grpcPort, scenario);
            await clientCache.StartupAsync(context).ShouldBeSuccess();

            var clientSession = clientCache.CreateSession(context, name: "TheSession", ImplicitPin.None).ShouldBeSuccess().Session;

            await clientSession.StartupAsync(context).ShouldBeSuccess();

            var piecesOfContent = 3;
            var putResults      = await Task.WhenAll(
                Enumerable.Range(0, piecesOfContent)
                .Select(_ => clientSession.PutRandomAsync(context, HashType.Vso0, provideHash: true, size: 128, context.Token).ShouldBeSuccess()));

            var contentHashList = new ContentHashList(putResults.Select(r => r.ContentHash).ToArray());
            var determinism     = CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow.AddDays(1));
            var contentHashListwithDeterminism = new ContentHashListWithDeterminism(contentHashList, determinism);

            var fingerprint       = new Fingerprint(ContentHash.Random().ToByteArray());
            var selector          = new Selector(ContentHash.Random(), output: new byte[] { 0, 42 });
            var strongFingerprint = new StrongFingerprint(fingerprint, selector);

            var cts = new CancellationTokenSource();
            // Even though publishing is blocking, this should succeed because we're publishing asynchronously.
            await clientSession.AddOrGetContentHashListAsync(context, strongFingerprint, contentHashListwithDeterminism, cts.Token).ShouldBeSuccess();

            // Allow for the publishing operation to be registered.
            await Task.Delay(TimeSpan.FromSeconds(1));

            // Simulate a restart.
            await server.ShutdownAsync(context).ShouldBeSuccess();

            server.Dispose();

            server = new LocalCacheServer(
                FileSystem,
                TestGlobal.Logger,
                scenario: scenario,
                cacheFactory: CreateBlockingPublishingCache,
                serverConfiguration,
                Capabilities.All);

            await server.StartupAsync(context).ShouldBeSuccess();

            // Session should have been persisted.
            var sessionsAndDatas = server.GetCurrentSessions();

            sessionsAndDatas.Length.Should().Be(1);
            var serverSession = sessionsAndDatas[0].session;
            var data          = sessionsAndDatas[0].data;

            var operation = new PublishingOperation
            {
                ContentHashListWithDeterminism = contentHashListwithDeterminism,
                StrongFingerprint = strongFingerprint
            };
            var operations = new[] { operation };

            data.Name.Should().Be(clientSession.Name);
            data.Pat.Should().Be(pat);
            data.Capabilities.Should().Be(Capabilities.All);
            data.ImplicitPin.Should().Be(ImplicitPin.None);
            data.Pins.Should().BeEquivalentTo(new List <string>());
            data.PublishingConfig.Should().BeEquivalentTo(publishingConfig);
            data.PendingPublishingOperations.Should().BeEquivalentTo(operations);

            var hibernateSession = serverSession as IHibernateCacheSession;

            hibernateSession.Should().NotBeNull();
            var actualPending = hibernateSession.GetPendingPublishingOperations();

            actualPending.Should().BeEquivalentTo(operations);

            await server.ShutdownAsync(context).ShouldBeSuccess();

            await clientSession.ShutdownAsync(context).ShouldBeSuccess();
        }
Exemple #18
0
 public void EmptyContentHashListWithDeterminismRoundtrip()
 {
     TestContentHashListWithDeterminismRoundtrip(new ContentHashListWithDeterminism(
                                                     ContentHashList.Random(contentHashCount: 0),
                                                     CacheDeterminism.ViaCache(CacheDeterminism.NewCacheGuid(), DateTime.UtcNow)));
 }
Exemple #19
0
        protected static IEnumerable <object[]> BuildDeterminismMatrix()
        {
            for (int i = -1; i < determinisms.Length; i++)
            {
                int localIndex = Math.Max(0, i);
                CacheDeterminism startDeterminismLocal  = determinisms[localIndex];
                CacheDeterminism startDeterminismRemote = determinisms[Math.Max(localIndex, 1)];
                CacheDeterminism endDetermismLocal      = startDeterminismLocal.IsDeterministicTool || startDeterminismRemote.IsDeterministicTool ? CacheDeterminism.Tool : CacheDeterminism.ViaCache(RemoteReferenceGuild, CacheDeterminism.NeverExpires);
                CacheDeterminism endDeterminismRemote   = startDeterminismRemote;

                yield return(new object[] { BackingStoreTestClass.Self, BackingStoreTestClass.Self, startDeterminismLocal, startDeterminismRemote, endDetermismLocal, endDeterminismRemote });
            }
        }
Exemple #20
0
 /// <nodoc />
 public static CacheDeterminism FromGrpc(this CacheDeterminismData input)
 {
     return(CacheDeterminism.ViaCache(
                new Guid(input.Guid.ToByteArray()),
                DateTime.SpecifyKind(new DateTime(input.ExpirationUtc), DateTimeKind.Utc)));
 }