Exemple #1
0
        private async Task ValidateSessionAsync(HashSet <FullCacheRecord> expectedRecords, ICache cache, string sessionId, FakeBuild.CasAccessMethod accessMethod)
        {
            if (!ImplementsTrackedSessions || DummySessionName != null)
            {
                return;
            }

            ICacheReadOnlySession readOnlySession = (await cache.CreateReadOnlySessionAsync()).Success();

            // Check that the content is fine
            HashSet <FullCacheRecord> foundRecords = new HashSet <FullCacheRecord>();

            foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(DummySessionName ?? sessionId).Success().OutOfOrderTasks())
            {
                StrongFingerprint strongFingerprint = await strongFingerprintTask;
                CasEntries        casEntries        = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success();
                FullCacheRecord   record            = new FullCacheRecord(strongFingerprint, casEntries);
                XAssert.IsTrue(expectedRecords.Contains(record), "Found record that was not expected!");
                foundRecords.Add(record);
            }

            (await readOnlySession.CloseAsync()).Success();

            await FakeBuild.CheckContentsAsync(cache, foundRecords, accessMethod);

            XAssert.AreEqual(expectedRecords.Count, foundRecords.Count);
        }
        /// <summary>
        /// Creates a FakeStrongFingerpint and the associated FakeBuild streams.
        /// </summary>
        /// <param name="pipName">Name of the pip</param>
        /// <param name="generateVerifiablePip">Determines if CheckContentsAsync can verify the contents of the build</param>
        /// <param name="pipSize">Number of files to include in the pip</param>
        /// <remarks>
        /// This method is the StrongFingerprint generation algorithm for FakeBuild.DoNondeterministicPipAsync
        /// </remarks>
        /// <returns>A FakeStrongFingerprint that has the FakeBuild class</returns>
        public static FakeStrongFingerprint Create(string pipName, bool generateVerifiablePip = false, int pipSize = 3)
        {
            FakeBuild           fake = new FakeBuild(pipName, pipSize, forceUniqueOutputs: !generateVerifiablePip);
            WeakFingerprintHash weak = CreateWeak(pipName.ToLowerInvariant());
            Hash simpleHash          = CreateHash(pipName.ToUpperInvariant());

            return(new FakeStrongFingerprint(weak, simpleHash, fake));
        }
Exemple #3
0
        public virtual async Task NonDeterministicContentRespectsDisconnect()
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(vertCache);

            ICacheSession aggregatorSession = (await testCache.CreateSessionAsync()).Success();
            ICacheSession localSession      = (await vertCache.LocalCache.CreateSessionAsync()).Success();
            ICacheSession remoteSession     = (await vertCache.RemoteCache.CreateSessionAsync()).Success();

            VerticalCacheAggregatorSession vertSession = aggregatorSession as VerticalCacheAggregatorSession;

            XAssert.IsNotNull(vertSession);

            CallbackCacheSessionWrapper wrappedSession = vertSession.RemoteSession as CallbackCacheSessionWrapper;

            XAssert.IsNotNull(wrappedSession);
            PoisonSession(wrappedSession);

            CacheDeterminism determinismSource = CacheDeterminism.None;

            const string PipName = "TestPip";

            // Populate the remote cache with one set of outputs.
            FullCacheRecord remoteCacheRecord = await FakeBuild.DoNonDeterministicPipAsync(remoteSession, PipName);

            // And the local cache with a set forced to be unique.
            FullCacheRecord localCacheRecord = await FakeBuild.DoNonDeterministicPipAsync(localSession, PipName, generateVerifiablePip: true);

            PoisonAllRemoteSessions(testCache);
            DisconnectRemoteCache(testCache);

            // Now query each cache, and verify only the remote content is in each.
            // Make sure the content is in each cache. (Placing the aggregator cache first will cause backfill of the local cache)
            foreach (var currentCache in new Tuple <ICache, CacheDeterminism, string, int>[]
            {
                new Tuple <ICache, CacheDeterminism, string, int>(testCache, CacheDeterminism.None, vertCache.LocalCache.CacheId, 1),
                new Tuple <ICache, CacheDeterminism, string, int>(vertCache.LocalCache, CacheDeterminism.None, vertCache.LocalCache.CacheId, 1)
            })
            {
                await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                    currentCache.Item1,
                    localCacheRecord.StrongFingerprint.WeakFingerprint,
                    new List <CasHash>(localCacheRecord.CasEntries),
                    currentCache.Item2,
                    localCacheRecord.StrongFingerprint.CasElement,
                    currentCache.Item3,
                    currentCache.Item4);
            }

            XAssert.IsTrue((await testCache.ShutdownAsync()).Succeeded);
        }
Exemple #4
0
        private async Task AddToEmptyCacheAsync(bool contentIsDeterministic)
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(vertCache);

            CacheDeterminism localDeterminism = CacheDeterminism.None;

            if (contentIsDeterministic)
            {
                localDeterminism = CacheDeterminism.Tool;
            }

            CacheDeterminism initialDeterminism = contentIsDeterministic ? CacheDeterminism.Tool : CacheDeterminism.None;

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

            VerticalCacheAggregatorSession vertSession = session as VerticalCacheAggregatorSession;

            XAssert.IsNotNull(vertSession);

            CallbackCacheSessionWrapper wrappedSession = vertSession.RemoteSession as CallbackCacheSessionWrapper;

            XAssert.IsNotNull(wrappedSession);
            PoisonSession(wrappedSession);
            DisconnectRemoteCache(testCache);

            FullCacheRecord cacheRecord = await FakeBuild.DoPipAsync(session, "TestPip", determinism: initialDeterminism);

            await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                vertCache.LocalCache,
                cacheRecord.StrongFingerprint.WeakFingerprint,
                new List <CasHash>(cacheRecord.CasEntries),
                localDeterminism,
                cacheRecord.StrongFingerprint.CasElement,
                vertCache.LocalCache.CacheId,
                1);

            await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                vertCache.RemoteCache,
                cacheRecord.StrongFingerprint.WeakFingerprint,
                new List <CasHash>(cacheRecord.CasEntries),
                localDeterminism,
                cacheRecord.StrongFingerprint.CasElement,
                vertCache.RemoteCache.CacheId,
                0);

            XAssert.IsTrue((await testCache.ShutdownAsync()).Succeeded);
        }
        public async Task NoItemFingerprint()
        {
            const string TestName    = nameof(NoItemFingerprint);
            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);

            // Note that we will be making a new fingerprint with a CasHash of NoItem
            // without pre-sending it as NoItem is a special case - it is nothing
            FullCacheRecord record = await FakeBuild.DoPipAsync(session, TestName);

            // We place this in and did not pin the NoItem yet or even send it around
            // Note that this also is doing a zero-length CasEntries
            var strong = new StrongFingerprint(record.StrongFingerprint.WeakFingerprint, CasHash.NoItem, new Hash(FingerprintUtilities.ZeroFingerprint), TestName);
            FullCacheRecordWithDeterminism oldRecord = (await session.AddOrGetAsync(
                                                            strong.WeakFingerprint,
                                                            strong.CasElement,
                                                            strong.HashElement,
                                                            CasEntries.FromCasHashes())).Success("Should work even though I did not pin CasHash.NoItem, instead it failed with {0}");

            XAssert.IsNull(oldRecord.Record, "Should have been the first one like this");

            var result = await session.GetCacheEntryAsync(strong).SuccessAsync();

            XAssert.AreEqual(0, result.Count, "We should have gotten a zero-length CasEntries");

            // We place this in and did not pin the NoItem yet or even send it around
            // Note that this does an array of NoItem CasEntries and use the
            // record.CasElement as the weak fingerprint
            CasHash[] empties = { CasHash.NoItem, CasHash.NoItem, CasHash.NoItem };
            strong    = new StrongFingerprint(new WeakFingerprintHash(strong.CasElement.ToFingerprint()), CasHash.NoItem, new Hash(FingerprintUtilities.ZeroFingerprint), TestName);
            oldRecord = (await session.AddOrGetAsync(
                             strong.WeakFingerprint,
                             CasHash.NoItem,
                             new Hash(FingerprintUtilities.ZeroFingerprint),
                             empties)).Success("Should work even though I did not pin CasHash.NoItem, instead it failed with {0}");

            XAssert.IsNull(oldRecord.Record, "Should have been the first one like this");

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

            XAssert.AreEqual(empties, result, "We should have gotten the set of empties");

            await CloseSessionAsync(session, testSessionId);

            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #6
0
        public virtual async Task WritethroughRemoteIsNotWrittenToWhenDisconnectedFileName()
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewWrappedRemoteCache(testCacheId, false, true)).SuccessAsync();

            PoisonAllRemoteSessions(testCache);
            DisconnectRemoteCache(testCache);

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

            FakeBuild fb = new FakeBuild("test", 1);

            AssertSuccess(await aggSession.AddToCasAsync(fb.Outputs[0]));
        }
        public async Task PinErrors()
        {
            const string TestName    = nameof(PinErrors);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

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

            FakeBuild fb = new FakeBuild("test", 3);

            var result = await session.PinToCasAsync(new CasHash(fb.OutputHashes[0]), CancellationToken.None);

            XAssert.IsFalse(result.Succeeded, "Pin should fail");
            XAssert.AreEqual(typeof(NoCasEntryFailure), result.Failure.GetType(), "Incorrect failure returned {0}", result.Failure.Describe());

            await CloseSessionAsync(session, null);
            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #8
0
        public async Task DisconnectedCacheNotQueriedForStrongFingerprints()
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            PoisonAllRemoteSessions(testCache);

            ICacheReadOnlySession roSession = await testCache.CreateReadOnlySessionAsync().SuccessAsync();

            DisconnectRemoteCache(testCache);

            FakeBuild fb = new FakeBuild("test", 1);

            foreach (var fingerprint in roSession.EnumerateStrongFingerprints(new WeakFingerprintHash(FingerprintUtilities.Hash("fingerprint").ToByteArray())))
            {
                // Just run the enumerator, should all return.
            }
        }
        public async Task AddWithoutPinWeak()
        {
            const string TestName    = nameof(AddWithoutPinWeak);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId, strictMetadataCasCoupling : false);

            // Only caches that are not strict metadata to CAS coupling need this test
            if (cache.StrictMetadataCasCoupling)
            {
                (await cache.ShutdownAsync()).Success();
                return;
            }

            string        testSessionId = "Session1-" + testCacheId;
            ICacheSession session       = await CreateSessionAsync(cache, testSessionId);

            FakeBuild fake = new FakeBuild(TestName, 2);

            // We fake up a CasHash - never actually add to the cache - weak cas
            CasHash inputList = fake.OutputListHash;

            CasHash[] items = new CasHash[fake.Outputs.Length];
            for (int i = 0; i < fake.Outputs.Length; i++)
            {
                items[i] = new CasHash(fake.OutputHashes[i]);
            }

            // We use the hash of our output list as the weak fingerprint and extra hash
            var outputListFingerprintHash = fake.OutputListHash.ToFingerprint();
            WeakFingerprintHash weak      = new WeakFingerprintHash(outputListFingerprintHash);

            // This should work since the session is weak.
            FullCacheRecordWithDeterminism record = (await session.AddOrGetAsync(weak, inputList, outputListFingerprintHash, items)).Success();

            XAssert.IsNull(record.Record, "There should not have been anything in the cache");

            // Doing it twice does not change things...
            record = (await session.AddOrGetAsync(weak, inputList, outputListFingerprintHash, items)).Success();
            XAssert.IsNull(record.Record, "It matches exactly, so no bother");

            await CloseSessionAsync(session, testSessionId);

            await ShutdownCacheAsync(cache, testCacheId);
        }
        public async Task GetWithoutPin()
        {
            const string TestName    = nameof(GetWithoutPin);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

            string        testSessionId = "Session1-" + testCacheId;
            ICacheSession session       = await CreateSessionAsync(cache, testSessionId);

            FakeBuild fake = new FakeBuild(TestName, 1);
            CasHash   item = (await session.AddToCasAsync(fake.OutputList)).Success();

            // Verify that we can read the content after it was added in
            // this session since it was pinned
            using (Stream stream = (await session.GetStreamAsync(item)).Success())
            {
                stream.AsString();
            }

            await CloseSessionAsync(session, testSessionId);

            testSessionId = "Session2-" + testCacheId;
            session       = await CreateSessionAsync(cache, testSessionId);

            if (RequiresPinBeforeGet)
            {
                // This time we will just get the content stream and it should fail
                // in this session since it is not open.
                var error = await session.GetStreamAsync(item);

                XAssert.IsTrue(!error.Succeeded, "Call to GetStream was successful, and should have failed for unpinned CAS access.");
                XAssert.IsTrue(error.Failure is UnpinnedCasEntryFailure, "Failed with unexpected error type {0} and error {1}", error.Failure, error.Failure.Describe());

                // Doing it twice did not change the case
                error = await session.GetStreamAsync(item);

                XAssert.IsTrue(!error.Succeeded, "Second call to GetStream was successful, and should have failed for unpinned CAS access.");
                XAssert.IsTrue(error.Failure is UnpinnedCasEntryFailure, "Failed with unexpected error type {0} and error {1}", error.Failure, error.Failure.Describe());
            }

            await CloseSessionAsync(session, testSessionId);

            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #11
0
        /// <summary>
        /// Execute a fake build based on this pip definition into the given cache session
        /// </summary>
        /// <param name="session">The cache session to use</param>
        /// <returns>The FullCacheRecord of the build operation</returns>
        public async Task <FullCacheRecord> BuildAsync(ICacheSession session)
        {
            Contract.Requires(session != null);

            FullCacheRecord record = await FakeBuild.DoPipAsync(
                session,
                pipName : PipName,
                pipSize : PipSize,
                weakIndex : WeakIndex,
                hashIndex : HashIndex,
                determinism : Determinism);

            if (Determinism.IsDeterministicTool)
            {
                XAssert.IsTrue(record.CasEntries.Determinism.IsDeterministicTool, "Tool was supposed to be deterministic");
            }

            return(record);
        }
        public async Task CacheMissTest()
        {
            const string TestName    = nameof(CacheMissTest);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

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

            FakeBuild fb = new FakeBuild("test", 3);

            StrongFingerprint fakeFingerprint = new StrongFingerprint(WeakFingerprintHash.Random(), new CasHash(fb.OutputHashes[0]), fb.OutputHashes[0], "fake");

            var response = await session.GetCacheEntryAsync(fakeFingerprint);

            XAssert.IsFalse(response.Succeeded);
            XAssert.AreEqual(typeof(NoMatchingFingerprintFailure), response.Failure.GetType(), response.Failure.Describe());

            await CloseSessionAsync(session, null);
            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #13
0
        private static async Task <FullCacheRecord> DoPipAsyncImpl(ICacheSession session,
                                                                   WeakFingerprintHash weak,
                                                                   Hash simpleHash,
                                                                   FakeBuild fake,
                                                                   CacheDeterminism determinism,
                                                                   CasAccessMethod accessMethod)
        {
            foreach (var strongTask in session.EnumerateStrongFingerprints(weak))
            {
                StrongFingerprint possibleHit = await strongTask.SuccessAsync();

                if (fake.OutputListHash.Equals(possibleHit.CasElement))
                {
                    if (simpleHash.Equals(possibleHit.HashElement))
                    {
                        // A cache hit!  Our strong fingerprint matched
                        return(new FullCacheRecord(possibleHit, await session.GetCacheEntryAsync(possibleHit).SuccessAsync()));
                    }
                }
            }

            // A cache miss - add the content to the cache and then
            // add the build.
            CasHash inputList = await AddToCasAsync(fake.OutputList, accessMethod, session).SuccessAsync();

            CasHash[] items = new CasHash[fake.Outputs.Length];
            for (int i = 0; i < items.Length; i++)
            {
                items[i] = await AddToCasAsync(fake.Outputs[i], accessMethod, session).SuccessAsync();
            }

            CasEntries entries = new CasEntries(items, determinism);

            FullCacheRecordWithDeterminism cacheRecord = await session.AddOrGetAsync(weak, inputList, simpleHash, entries).SuccessAsync();

            XAssert.AreEqual(null, cacheRecord.Record);

            // Produce a full cache record manually - such that the CacheId is our own "NewRecordCacheId"
            return(new FullCacheRecord(new StrongFingerprint(weak, inputList, simpleHash, NewRecordCacheId), entries));
        }
        public async Task CacheDataPersistedReadOnlyCache()
        {
            string testName = "CacheDataPersistedReadOnly";

            ICache firstInvocation = await CreateCacheAsync(testName, true);

            Guid originalGuid = firstInvocation.CacheGuid;

            ICacheSession session = (await firstInvocation.CreateSessionAsync("sessionName")).Success();

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

            (await session.CloseAsync()).Success();
            await ShutdownCacheAsync(firstInvocation, testName);

            ICache secondInvocation = await GetExistingCacheAsync(testName, true, true);

            XAssert.AreEqual(originalGuid, secondInvocation.CacheGuid, "Persistent caches: GUID should not change");

            XAssert.IsTrue(secondInvocation.IsReadOnly, "This should have been a read-only cache");

            ICacheReadOnlySession newSession = (await secondInvocation.CreateReadOnlySessionAsync()).Success();

            int fingerprintsFound = 0;

            foreach (var singleFingerprint in newSession.EnumerateStrongFingerprints(cacheRecord.StrongFingerprint.WeakFingerprint))
            {
                var sfp = (await singleFingerprint).Success();

                XAssert.AreEqual(cacheRecord.StrongFingerprint, sfp, "Fingerprints must match");

                fingerprintsFound++;
            }

            XAssert.AreEqual(1, fingerprintsFound, "A single instance of the fingerprint should have been found after restarting the cache.");

            (await newSession.CloseAsync()).Success();

            await ShutdownCacheAsync(secondInvocation, testName);
        }
Exemple #15
0
        /// <summary>
        /// This will do a build into the session with a given name
        /// and output count.
        /// </summary>
        /// <param name="session">The cache session to work with</param>
        /// <param name="pipName">Some text that acts as a base element in the output</param>
        /// <param name="pipSize">Number of elements in the output.  Must be enough to cover the variants</param>
        /// <param name="weakIndex">Variant with different weak index - defaults to 1</param>
        /// <param name="hashIndex">Variant with different hash index - defaults to 0</param>
        /// <param name="accessMethod">Method (File or stream) for how files are materialized from the cache</param>
        /// <param name="determinism">Determinism to provide for new build records</param>
        /// <returns>The FullCacheRecord of the build</returns>
        /// <remarks>
        /// This will do a "fake build" including a cache lookup via weak fingerprints
        /// and then return either the existing FullCacheRecord or add the build as a new
        /// one.  A new FullCacheRecord will have the StrongFingerprint.CacheId set to NewRecordCacheId
        /// </remarks>
        public static Task <FullCacheRecord> DoPipAsync(
            ICacheSession session,
            string pipName,
            int pipSize   = DefaultFakeBuildSize,
            int weakIndex = 1,
            int hashIndex = 0,
            CacheDeterminism determinism = default(CacheDeterminism),
            CasAccessMethod accessMethod = CasAccessMethod.Stream)
        {
            Contract.Requires(session != null);
            Contract.Requires(pipName != null);
            Contract.Requires(pipSize > 0);
            Contract.Requires(weakIndex >= 0 && weakIndex < pipSize);
            Contract.Requires(hashIndex >= 0 && hashIndex < pipSize);

            FakeBuild fake = new FakeBuild(pipName, pipSize);

            WeakFingerprintHash weak = new WeakFingerprintHash(FingerprintUtilities.Hash(fake.OutputHashes[weakIndex].ToString()).ToByteArray());
            Hash simpleHash          = new Hash(FingerprintUtilities.Hash(fake.OutputHashes[hashIndex].ToString()));

            return(DoPipAsyncImpl(session, weak, simpleHash, fake, determinism, accessMethod));
        }
        public async Task ProduceFileWithDirectories(FileState fileState)
        {
            const string TestName    = nameof(ProduceFileWithDirectories);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

            string        testSessionId = "Session1-" + testCacheId;
            ICacheSession session       = await CreateSessionAsync(cache, testSessionId);

            FakeBuild fake = new FakeBuild(TestName, 1);
            CasHash   item = await session.AddToCasAsync(fake.OutputList).SuccessAsync();

            // Now, lets make a temp file name with a path that does not exist
            // We need to make sure it gets produced during ProduceFile
            string tmpFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("D"), "Test.txt");
            await session.ProduceFileAsync(item, tmpFile, fileState).SuccessAsync("Did not produce a file with a directory that did not exist!");

            Directory.Delete(Path.GetDirectoryName(tmpFile), true);

            await CloseSessionAsync(session, testSessionId);
            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #17
0
        public virtual async Task ReadOnlyRemoteIsNotUpdatedWhenDisconnected()
        {
            string testCacheId = "Disconnected";
            ICache testCache   = await InitializeCacheAsync(NewCache(testCacheId, false)).SuccessAsync();

            VerticalCacheAggregator vertCache = testCache as VerticalCacheAggregator;

            XAssert.IsNotNull(vertCache);

            PoisonAllRemoteSessions(testCache);
            DisconnectRemoteCache(testCache);

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

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

            await VerticalAggregatorBaseTests.ValidateItemsInCacheAsync(
                vertCache.LocalCache,
                cacheRecord.StrongFingerprint.WeakFingerprint,
                new List <CasHash>(cacheRecord.CasEntries),
                CacheDeterminism.None,
                cacheRecord.StrongFingerprint.CasElement,
                vertCache.LocalCache.CacheId,
                1);

            var remoteSession = await vertCache.RemoteCache.CreateReadOnlySessionAsync().SuccessAsync();

            int fingerprintsReturned = 0;

            foreach (var fingerprint in remoteSession.EnumerateStrongFingerprints(cacheRecord.StrongFingerprint.WeakFingerprint))
            {
                fingerprintsReturned++;
            }

            XAssert.AreEqual(0, fingerprintsReturned, "No fingerprints should have been found in the remote cache.");
            AssertSuccess(await testCache.ShutdownAsync());
        }
        public async Task AddWithoutPin()
        {
            const string TestName    = nameof(AddWithoutPin);
            string       testCacheId = MakeCacheId(TestName);
            ICache       cache       = await CreateCacheAsync(testCacheId);

            string        testSessionId = "Session1-" + testCacheId;
            ICacheSession session       = await CreateSessionAsync(cache, testSessionId);

            FakeBuild fake = new FakeBuild(TestName, 2);

            CasHash inputList = (await session.AddToCasAsync(fake.OutputList)).Success();

            // Verify that we can read the content after it was added in
            // this session since it was pinned
            using (Stream stream = (await session.GetStreamAsync(inputList)).Success())
            {
                stream.AsString();
            }

            CasHash[] items = new CasHash[fake.Outputs.Length];
            for (int i = 0; i < fake.Outputs.Length; i++)
            {
                items[i] = (await session.AddToCasAsync(fake.Outputs[i])).Success();

                // Verify that we can read the content after it was added in
                // this session since it was pinned
                using (Stream stream = (await session.GetStreamAsync(items[i])).Success())
                {
                    stream.AsString();
                }
            }

            await CloseSessionAsync(session, testSessionId);

            testSessionId = "Session2-" + testCacheId;
            session       = await CreateSessionAsync(cache, testSessionId);

            // We use the hash of our output list as the weak fingerprint and extra hash
            var outputListFingerprintHash = fake.OutputListHash.ToFingerprint();
            WeakFingerprintHash weak      = new WeakFingerprintHash(outputListFingerprintHash);

            if (cache.StrictMetadataCasCoupling)
            {
                // This should fail as we did not pin or add the content yet
                var error = await session.AddOrGetAsync(weak, inputList, outputListFingerprintHash, items);

                XAssert.IsFalse(error.Succeeded, "Add of weak fingerprint when items not first added to CAS was successful.");
                XAssert.IsTrue(error.Failure is UnpinnedCasEntryFailure, "Error failure was not expected type {0}, it was {1} {2}", typeof(UnpinnedCasEntryFailure).Name, error.Failure.GetType().Name, error.Failure.Describe());

                // Doing it twice does not change things...
                error = await session.AddOrGetAsync(weak, inputList, outputListFingerprintHash, items);

                XAssert.IsFalse(error.Succeeded, "Add of weak fingerprint when items not first added to CAS was successful.");
                XAssert.IsTrue(error.Failure is UnpinnedCasEntryFailure, "Error failure was not expected type {0}, it was {1}, {2}", typeof(UnpinnedCasEntryFailure).Name, error.Failure.GetType().Name, error.Failure.Describe());
            }

            await CloseSessionAsync(session, testSessionId);

            await ShutdownCacheAsync(cache, testCacheId);
        }
Exemple #19
0
        public async Task SimpleDummySession()
        {
            const string TestName    = "SimpleSession";
            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);

            // Do the default fake build for this test (first time, no cache hit)
            FullCacheRecord built = await FakeBuild.DoPipAsync(session, TestName);

            XAssert.AreEqual(FakeBuild.NewRecordCacheId, built.CacheId, "Should have been a new cache entry!");

            // Now we see if we can get back the items we think we should
            await CloseSessionAsync(session, testSessionId);

            // We need a read only session to get the CasEntries
            ICacheReadOnlySession readOnlySession = (await cache.CreateReadOnlySessionAsync()).Success();

            // Validate that the cache contains a dummy session and it has the one cache record it needs.
            HashSet <FullCacheRecord> found = new HashSet <FullCacheRecord>();

            foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(MemoizationStoreAdapterCache.DummySessionName).Success().OutOfOrderTasks())
            {
                StrongFingerprint strongFingerprint = await strongFingerprintTask;
                CasEntries        casEntries        = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success();
                FullCacheRecord   record            = new FullCacheRecord(strongFingerprint, casEntries);

                // If it is not the record we already found...
                if (!found.Contains(record))
                {
                    found.Add(record);
                }

                XAssert.AreEqual(1, found.Count, "There should be only 1 unique record in the session");

                XAssert.AreEqual(built.StrongFingerprint.WeakFingerprint, record.StrongFingerprint.WeakFingerprint);
                XAssert.AreEqual(built.StrongFingerprint.CasElement, record.StrongFingerprint.CasElement);
                XAssert.AreEqual(built.StrongFingerprint.HashElement, record.StrongFingerprint.HashElement);
                XAssert.AreEqual(built.CasEntries.Count, record.CasEntries.Count, "Did not return the same number of items");
                XAssert.IsTrue(record.CasEntries.Equals(built.CasEntries), "Items returned are not the same hash and/or order order");

                XAssert.AreEqual(built, record);

                // We can not check record.CasEntries.IsDeterministic
                // as the cache may have determined that they are deterministic
                // via cache determinism recovery.
            }

            XAssert.AreEqual(1, found.Count, "There should be 1 and only 1 record in the session!");

            await readOnlySession.CloseAsync().SuccessAsync();

            // Check that the cache has the items in it
            await FakeBuild.CheckContentsAsync(cache, built);

            // Now redo the "build" with a cache hit
            testSessionId = "Session2-" + testCacheId;
            session       = await CreateSessionAsync(cache, testSessionId);

            FullCacheRecord rebuilt = await FakeBuild.DoPipAsync(session, TestName);

            XAssert.AreEqual(built, rebuilt, "Should have been the same build!");

            // We make sure we did get it from a cache rather than a manual rebuild.
            XAssert.AreNotEqual(built.CacheId, rebuilt.CacheId, "Should not be the same cache ID");

            await CloseSessionAsync(session, testSessionId);

            readOnlySession = await cache.CreateReadOnlySessionAsync().SuccessAsync();

            // Now that we have done the second build via a cache hit, it should produce the
            // same cache record as before
            foreach (var strongFingerprintTask in cache.EnumerateSessionStrongFingerprints(MemoizationStoreAdapterCache.DummySessionName).Success().OutOfOrderTasks())
            {
                StrongFingerprint strongFingerprint = await strongFingerprintTask;
                CasEntries        casEntries        = (await readOnlySession.GetCacheEntryAsync(strongFingerprint)).Success();
                FullCacheRecord   record            = new FullCacheRecord(strongFingerprint, casEntries);

                XAssert.IsTrue(found.Contains(record), "Second session should produce the same cache record but did not!");
            }

            (await readOnlySession.CloseAsync()).Success();

            await ShutdownCacheAsync(cache, testCacheId);
        }
 private FakeStrongFingerprint(WeakFingerprintHash weak, Hash hashElement, FakeBuild fake)
     : base(weak, fake.OutputListHash, hashElement, "FakeCache")
 {
     FakeBuild = fake;
 }