Beispiel #1
0
        public void CacheEntryGettersDefaultConstructors()
        {
            BuildItem[] buildItems = new BuildItem[2] { null, null };

            BuildItemCacheEntry tice = new BuildItemCacheEntry();
            Assertion.AssertEquals(null, tice.Name);
            Assertion.AssertEquals(null, tice.BuildItems);
            
            tice.Name = "tice";
            tice.BuildItems = buildItems;
            Assertion.AssertEquals("tice", tice.Name);
            Assertion.AssertEquals(buildItems, tice.BuildItems);

            PropertyCacheEntry pce = new PropertyCacheEntry();
            Assertion.AssertEquals(null, pce.Name);
            Assertion.AssertEquals(null, pce.Value);

            pce.Name = "pce";
            pce.Value = "propertyValue";
            Assertion.AssertEquals("pce", pce.Name);
            Assertion.AssertEquals("propertyValue", pce.Value);

            BuildResultCacheEntry brce = new BuildResultCacheEntry();
            Assertion.AssertEquals(null, brce.Name);
            Assertion.AssertEquals(null, brce.BuildItems);
            Assertion.AssertEquals(default(bool), brce.BuildResult);

            brce.Name = "brce";
            brce.BuildItems = buildItems;
            brce.BuildResult = false;
            Assertion.AssertEquals("brce", brce.Name);
            Assertion.AssertEquals(buildItems, brce.BuildItems);
            Assertion.AssertEquals(false, brce.BuildResult);
        }
        internal static CacheEntry CreateFromStream(BinaryReader reader)
        {
            CacheEntryTypes entryType = (CacheEntryTypes)reader.ReadByte();
            CacheEntry      entry     = null;

            switch (entryType)
            {
            case CacheEntryTypes.BuildItem:
                entry = new BuildItemCacheEntry();
                break;

            case CacheEntryTypes.BuildResult:
                entry = new BuildResultCacheEntry();
                break;

            case CacheEntryTypes.Property:
                entry = new PropertyCacheEntry();
                break;

            default:
                ErrorUtilities.VerifyThrow(false, "Should not get to the default of CacheEntryCustomSerializer CreateFromStream");
                break;
            }

            entry.CreateFromStream(reader);
            return(entry);
        }
Beispiel #3
0
 public void CheckBasicOperation()
 {
     CacheManager cacheManager = new CacheManager("3.5");
     CacheScope cacheScope = cacheManager.GetCacheScope("Test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items);
     Assert.IsNotNull(cacheScope, "Cache should not have an entry");
     CacheScope cacheScope1 = cacheManager.GetCacheScope("Test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items);
     Assert.AreEqual(cacheScope, cacheScope1, "Expected to get the same scope");
     cacheScope1 = cacheManager.GetCacheScope("Test1.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items);
     Assert.IsNotNull(cacheScope1, "Cache should not have an entry");
     Assert.AreNotEqual(cacheScope, cacheScope1, "Expected to get different scopes");
     // Add an entry and verify that it ends up in the right scope
     CacheEntry cacheEntry = new BuildResultCacheEntry("TestEntry", null, true);
     CacheEntry cacheEntry1 = new BuildResultCacheEntry("TestEntry1", null, true);
     cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "Test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items);
     Assert.IsNotNull(cacheScope.GetCacheEntry("TestEntry"), "Cache should have an entry");
     Assert.IsNotNull(cacheManager.GetCacheEntries(new string[] { "TestEntry" }, "Test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items)[0],
                      "Cache should have an entry");
     cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry1 }, "Test1.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items);
     Assert.IsNotNull(cacheScope1.GetCacheEntry("TestEntry1"), "Cache should have an entry");
     Assert.IsNotNull(cacheManager.GetCacheEntries(new string[] { "TestEntry1" }, "Test1.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items)[0],
          "Cache should have an entry");
     // Try clearing the whole cache
     cacheManager.ClearCache();
     Assert.AreNotEqual(cacheScope, cacheManager.GetCacheScope("Test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.Items),
                        "Expected to get different scopes");
 }
Beispiel #4
0
        public void CacheEntryGetters()
        {
            BuildItem[] buildItems = new BuildItem[2] { null, null };

            BuildItemCacheEntry tice = new BuildItemCacheEntry("tice", buildItems);
            Assertion.AssertEquals("tice", tice.Name);
            Assertion.AssertEquals(buildItems, tice.BuildItems);

            PropertyCacheEntry pce = new PropertyCacheEntry("pce", "propertyValue");
            Assertion.AssertEquals("pce", pce.Name);
            Assertion.AssertEquals("propertyValue", pce.Value);

            BuildResultCacheEntry brce = new BuildResultCacheEntry("brce", buildItems, true);
            Assertion.AssertEquals("brce", brce.Name);
            Assertion.AssertEquals(buildItems, brce.BuildItems);
            Assertion.AssertEquals(true, brce.BuildResult);
        }
Beispiel #5
0
 public void BasicCacheOperation()
 {
     BuildPropertyGroup default_scope = new BuildPropertyGroup();
     CacheScope testScope = new CacheScope("Test.proj", new BuildPropertyGroup(), "2.0");
     // First add a single entry and verify that it is in the cache
     CacheEntry cacheEntry = new BuildResultCacheEntry("TestEntry", null, true);
     testScope.AddCacheEntry(cacheEntry);
     Assert.IsTrue(testScope.ContainsCacheEntry("TestEntry"), "Expect entry in the cache");
     CacheEntry inCacheEntry = testScope.GetCacheEntry("TestEntry");
     Assert.IsNotNull(inCacheEntry, "Cache should have an entry");
     Assert.IsTrue(inCacheEntry.IsEquivalent(cacheEntry), "Expect entry to be the same");
     // Add a second entry and then remove the first entry. Verify that the first entry
     // is not in the cache while the second entry is still there
     cacheEntry = new BuildResultCacheEntry("TestEntry2", null, true);
     testScope.AddCacheEntry(cacheEntry);
     testScope.ClearCacheEntry("TestEntry");
     Assert.IsFalse(testScope.ContainsCacheEntry("TestEntry"), "Didn't expect entry in the cache");
     Assert.IsTrue(testScope.ContainsCacheEntry("TestEntry2"), "Expected entry in the cache");
     Assert.IsNull(testScope.GetCacheEntry("TestEntry"), "Cache should  not have an entry");
     Assert.IsNotNull(testScope.GetCacheEntry("TestEntry2"), "Cache should have an entry");
 }
        internal static CacheEntry CreateFromStream(BinaryReader reader)
        {
            CacheEntryTypes entryType = (CacheEntryTypes) reader.ReadByte();
            CacheEntry entry = null;

            switch (entryType)
            {
                case CacheEntryTypes.BuildItem:
                    entry = new BuildItemCacheEntry();
                    break;
                case CacheEntryTypes.BuildResult:
                    entry = new BuildResultCacheEntry();
                    break;
                case CacheEntryTypes.Property:
                    entry = new PropertyCacheEntry();
                    break;
                default:
                    ErrorUtilities.VerifyThrow(false, "Should not get to the default of CacheEntryCustomSerializer CreateFromStream");
                    break;
            }

            entry.CreateFromStream(reader);
            return entry;
        }
Beispiel #7
0
        public void TestCacheEntryCustomSerialization()
        {
            // Stream, writer and reader where the events will be serialized and deserialized from
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream);
            BinaryReader reader = new BinaryReader(stream);
            try
            {
                BuildItem buildItem1 = new BuildItem("BuildItem1", "Item1");
                BuildItem buildItem2 = new BuildItem("BuildItem2", "Item2");
                buildItem1.Include = "TestInclude1";
                buildItem2.Include = "TestInclude2";
                BuildItem[] buildItems = new BuildItem[2];
                buildItems[0] = buildItem1;
                buildItems[1] = buildItem2;

                BuildItemCacheEntry buildItemEntry = new BuildItemCacheEntry("Badger", buildItems);
                BuildResultCacheEntry buildResultEntry = new BuildResultCacheEntry("Koi", buildItems, true);
                PropertyCacheEntry propertyEntry = new PropertyCacheEntry("Seagull", "bread");
                
                stream.Position = 0;
                // Serialize
                buildItemEntry.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                long streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                BuildItemCacheEntry newCacheEntry = new BuildItemCacheEntry();
                newCacheEntry.CreateFromStream(reader);
                long streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(string.Compare(newCacheEntry.Name, buildItemEntry.Name, StringComparison.OrdinalIgnoreCase) == 0);
                BuildItem[] buildItemArray = newCacheEntry.BuildItems;
                Assert.IsTrue(buildItemArray.Length == 2);
                Assert.IsTrue(string.Compare(buildItemArray[0].Include, buildItem1.Include, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Include, buildItem2.Include, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Name, buildItem2.Name, StringComparison.OrdinalIgnoreCase) == 0);


                stream.Position = 0;
                // Serialize
                buildResultEntry.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                BuildResultCacheEntry newCacheEntryBuildResult = new BuildResultCacheEntry();
                newCacheEntryBuildResult.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(string.Compare(newCacheEntryBuildResult.Name, buildResultEntry.Name, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(buildResultEntry.BuildResult == newCacheEntryBuildResult.BuildResult);
                buildItemArray = newCacheEntryBuildResult.BuildItems;
                Assert.IsTrue(buildItemArray.Length == 2);
                Assert.IsTrue(string.Compare(buildItemArray[0].Include, buildItem1.Include, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Include, buildItem2.Include, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(buildItemArray[1].Name, buildItem2.Name, StringComparison.OrdinalIgnoreCase) == 0);


                stream.Position = 0;
                // Serialize
                propertyEntry.WriteToStream(writer);
                // Get position of stream after write so it can be compared to the position after read
                streamWriteEndPosition = stream.Position;

                // Deserialize and Verify
                stream.Position = 0;
                PropertyCacheEntry newPropertyCacheEntry = new PropertyCacheEntry();
                newPropertyCacheEntry.CreateFromStream(reader);
                streamReadEndPosition = stream.Position;
                Assert.IsTrue(streamWriteEndPosition == streamReadEndPosition, "Stream End Positions Should Match");
                Assert.IsTrue(string.Compare(newPropertyCacheEntry.Name, propertyEntry.Name, StringComparison.OrdinalIgnoreCase) == 0);
                Assert.IsTrue(string.Compare(newPropertyCacheEntry.Value, propertyEntry.Value, StringComparison.OrdinalIgnoreCase) == 0);
            }
            finally
            {
                // Close will close the writer/reader and the underlying stream
                writer.Close();
                reader.Close();
                reader = null;
                stream = null;
                writer = null;
            }
        }
Beispiel #8
0
        public void IsEquivalentBuildResult()
        {
            BuildResultCacheEntry e = new BuildResultCacheEntry("name", null, false);

            Assert.IsFalse(e.IsEquivalent(null));
            Assert.IsFalse(e.IsEquivalent(new PropertyCacheEntry("name", "value")));
            Assert.IsFalse(e.IsEquivalent(new BuildItemCacheEntry("name", null)));
            Assert.IsFalse(e.IsEquivalent(new BuildResultCacheEntry()));
            Assert.IsFalse(e.IsEquivalent(new BuildResultCacheEntry("naame", null, false)));
            Assert.IsFalse(e.IsEquivalent(new BuildResultCacheEntry("name", null, true)));
            Assert.IsTrue(e.IsEquivalent(new BuildResultCacheEntry("name", null, false)));
        }
Beispiel #9
0
        /// <summary>
        /// Get a cached build result if available for the given request. This method is thread safe.
        /// </summary>
        /// <param name="buildRequest"></param>
        /// <param name="actuallyBuiltTargets"></param>
        /// <returns></returns>
        internal BuildResult GetCachedBuildResult(BuildRequest buildRequest, out ArrayList actuallyBuiltTargets)
        {
            actuallyBuiltTargets = null;

            PropertyCacheEntry defaultTargetsCacheEntry, initialTargetsCacheEntry, projectIdCacheEntry;

            // No writes here, but since we're reading multiple values we want to get a consistent view of the cache
            cacheScopeReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            try
            {
                defaultTargetsCacheEntry = (PropertyCacheEntry)GetCacheEntry(Constants.defaultTargetCacheName);
                initialTargetsCacheEntry = (PropertyCacheEntry)GetCacheEntry(Constants.initialTargetCacheName);
                projectIdCacheEntry      = (PropertyCacheEntry)GetCacheEntry(Constants.projectIdCacheName);
            }
            finally
            {
                cacheScopeReaderWriterLock.ReleaseReaderLock();
            }

            // If we ever built anything in this project we must have the default and initial targets.
            if (defaultTargetsCacheEntry == null && initialTargetsCacheEntry == null)
            {
                return(null);
            }

            ErrorUtilities.VerifyThrow(projectIdCacheEntry != null, "We should always have the projectId cache entry");

            ErrorUtilities.VerifyThrow(defaultTargetsCacheEntry != null && initialTargetsCacheEntry != null,
                                       "We should have both the initial and default targets in the cache");

            ArrayList targetsToBuild = new ArrayList(initialTargetsCacheEntry.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));

            if (buildRequest.TargetNames == null || buildRequest.TargetNames.Length == 0)
            {
                targetsToBuild.AddRange(defaultTargetsCacheEntry.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
            }
            else
            {
                targetsToBuild.AddRange(buildRequest.TargetNames);
            }

            // Create variable to hold the cached outputs
            Hashtable outputsByTargetName = new Hashtable(targetsToBuild.Count);
            Hashtable resultByTarget      = new Hashtable(targetsToBuild.Count, StringComparer.OrdinalIgnoreCase);

            bool overallSuccess = true;
            bool missingValues  = false;

            // No writes here, but since we're reading multiple values we want to get a consistent view of the cache
            cacheScopeReaderWriterLock.AcquireReaderLock(Timeout.Infinite);

            try
            {
                for (int i = 0; i < targetsToBuild.Count; i++)
                {
                    string targetName = EscapingUtilities.UnescapeAll((string)targetsToBuild[i]);
                    if (ContainsCacheEntry(targetName))
                    {
                        BuildResultCacheEntry cacheEntry = (BuildResultCacheEntry)GetCacheEntry(targetName);
                        overallSuccess             = overallSuccess && cacheEntry.BuildResult;
                        resultByTarget[targetName] = (cacheEntry.BuildResult) ?
                                                     Target.BuildState.CompletedSuccessfully : Target.BuildState.CompletedUnsuccessfully;

                        // Restore output items for successful targets
                        if (cacheEntry.BuildResult)
                        {
                            outputsByTargetName[targetName] = cacheEntry.BuildItems;
                        }
                        // We found a failed target - cut the loop short
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        missingValues = true;
                        break;
                    }
                }
            }
            finally
            {
                cacheScopeReaderWriterLock.ReleaseReaderLock();
            }

            if (missingValues)
            {
                return(null);
            }

            actuallyBuiltTargets = targetsToBuild;

            return(new BuildResult(outputsByTargetName, resultByTarget, overallSuccess, buildRequest.HandleId, buildRequest.RequestId,
                                   int.Parse(projectIdCacheEntry.Value, CultureInfo.InvariantCulture), false /* use results cache */,
                                   defaultTargetsCacheEntry.Value, initialTargetsCacheEntry.Value, 0, 0, 0));
        }
Beispiel #10
0
        /// <summary>
        /// This method adds cached results for each target results for which are contained inside
        /// the build result. This method is thread safe.
        /// </summary>
        internal void AddCacheEntryForBuildResults(BuildResult buildResult)
        {
            ErrorUtilities.VerifyThrow(buildResult != null, "Expect a non-null build result");

            // Don't cache results if they are marked as uncacheable
            if (!buildResult.UseResultCache)
            {
                return;
            }

            cacheScopeReaderWriterLock.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (!ContainsCacheEntry(Constants.defaultTargetCacheName))
                {
                    // If the project file is malformed the build may fail without initializing the initialtargets or
                    // the default targests fields. The retrieval code expects non-null values
                    // so it is necessary to replace null with empty string
                    ErrorUtilities.VerifyThrow(!buildResult.EvaluationResult || (buildResult.InitialTargets != null &&
                                                                                 buildResult.DefaultTargets != null),
                                               "Expect initial targets to be non-null for successful builds");
                    string             defaultTargets           = buildResult.DefaultTargets ?? String.Empty;
                    PropertyCacheEntry defaultTargetsCacheEntry = new PropertyCacheEntry(Constants.defaultTargetCacheName, defaultTargets);
                    AddCacheEntryInternal(defaultTargetsCacheEntry);

                    string             initialTargets           = buildResult.InitialTargets ?? String.Empty;
                    PropertyCacheEntry initialTargetsCacheEntry = new PropertyCacheEntry(Constants.initialTargetCacheName, initialTargets);
                    AddCacheEntryInternal(initialTargetsCacheEntry);
                }

                if (!ContainsCacheEntry(Constants.projectIdCacheName))
                {
                    PropertyCacheEntry projectIdCacheEntry = new PropertyCacheEntry(Constants.projectIdCacheName, buildResult.ProjectId.ToString(CultureInfo.InvariantCulture));
                    AddCacheEntryInternal(projectIdCacheEntry);
                }

                IDictionary outputsByTargetName = buildResult.OutputsByTarget;

                //Create single entry for each target in the request
                foreach (DictionaryEntry entry in buildResult.ResultByTarget)
                {
                    Target.BuildState buildState = (Target.BuildState)entry.Value;

                    // Only cache successful and failed targets
                    if ((buildState == Target.BuildState.CompletedSuccessfully) ||
                        (buildState == Target.BuildState.CompletedUnsuccessfully))
                    {
                        BuildItem[] targetOutputs = null;

                        // Only cache output items for successful targets
                        if (buildState == Target.BuildState.CompletedSuccessfully)
                        {
                            ErrorUtilities.VerifyThrow(buildResult.OutputsByTarget.Contains(entry.Key),
                                                       "We must have build results for successful targets");

                            BuildItem[] outputItems = (BuildItem[])buildResult.OutputsByTarget[entry.Key];

                            // It's essential that we clear out any pointers to the project from the BuildItem;
                            // otherwise the cache will hold onto the project, and not save any memory.
                            if (outputItems != null)
                            {
                                for (int i = 0; i < outputItems.Length; i++)
                                {
                                    outputItems[i] = outputItems[i].VirtualClone(true /* remove references to minimise transitive size */);
                                }
                            }

                            targetOutputs = (BuildItem[])buildResult.OutputsByTarget[entry.Key];
                        }

                        BuildResultCacheEntry cacheEntry = new BuildResultCacheEntry((string)entry.Key, targetOutputs,
                                                                                     buildState == Target.BuildState.CompletedSuccessfully);

                        if (Engine.debugMode)
                        {
                            Console.WriteLine("+++Adding cache entry for " + (string)entry.Key + " in " +
                                              this.ScopeName + " result: " + (buildState == Target.BuildState.CompletedSuccessfully));
                        }

                        AddCacheEntryInternal(cacheEntry);
                    }
                }
            }
            finally
            {
                cacheScopeReaderWriterLock.ReleaseWriterLock();
            }
        }
Beispiel #11
0
        private static CacheEntry[] CreateCacheEntries()
        {
            CacheEntry[] entries = new CacheEntry[3];

            BuildItem buildItem1 = new BuildItem("BuildItem1", "Item1");
            BuildItem buildItem2 = new BuildItem("BuildItem2", "Item2");
            buildItem1.Include = "TestInclude1";
            buildItem2.Include = "TestInclude2";
            BuildItem[] buildItems = new BuildItem[2];
            buildItems[0] = buildItem1;
            buildItems[1] = buildItem2;

            entries[0] = new BuildItemCacheEntry("Badger", buildItems);
            entries[1] = new BuildResultCacheEntry("Koi", buildItems, true);
            entries[2] = new PropertyCacheEntry("Seagull", "bread");
            return entries;
        }
Beispiel #12
0
        public void TestRequestCaching()
        {
            CacheManager cacheManager = new CacheManager("3.5");

            ArrayList actuallyBuiltTargets;

            // Test the case where we pass in null targets
            Dictionary<string, string> dictionary = new Dictionary<string,string>();
            BuildRequest emptyRequest = new BuildRequest(1, "test.proj", null, dictionary, null, 1, true, false);

            Assert.IsNull(cacheManager.GetCachedBuildResult(emptyRequest, out actuallyBuiltTargets), "Expect a null return value if T=null");

            // Test the case where we pass in length 0 targets
            BuildRequest length0Request = new BuildRequest(1, "test.proj", new string[0], dictionary, null, 1, true, false);
            Assert.IsNull(cacheManager.GetCachedBuildResult(length0Request, out actuallyBuiltTargets), "Expect a null return value if T.Length=0");

            // Test the case when the scope doesn't exist
            string[] targets = new string[1]; targets[0] = "Target1";
            BuildRequest length1Request = new BuildRequest(1, "test.proj", targets, new BuildPropertyGroup(), null, 1, true, false);
            Assert.IsNull(cacheManager.GetCachedBuildResult(length1Request, out actuallyBuiltTargets), "Expect a null return value if no scope");
            
            // Test the case when the scope exists but is empty
            CacheScope cacheScope = cacheManager.GetCacheScope("test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            Assert.IsNull(cacheManager.GetCachedBuildResult(length1Request, out actuallyBuiltTargets), "Expect a null return value if scope is empty");
            
            // Test the case when the scope exists but contains wrong data
            CacheEntry cacheEntry = new BuildResultCacheEntry("Target2", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            Assert.IsNull(cacheManager.GetCachedBuildResult(length1Request, out actuallyBuiltTargets), "Expect a null return value if scope contains wrong data");
            
            // Test the case when everything is correct
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.defaultTargetCacheName, string.Empty));
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.initialTargetCacheName, string.Empty));
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.projectIdCacheName, "1"));
            
            cacheEntry = new BuildResultCacheEntry("Target1", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            BuildResult buildResult = cacheManager.GetCachedBuildResult(length1Request, out actuallyBuiltTargets);
            Assert.IsNotNull(buildResult, "Expect a cached value if scope contains data");
            Assert.AreEqual(1, actuallyBuiltTargets.Count);
            Assert.AreEqual("Target1", actuallyBuiltTargets[0]);
            Assert.AreEqual(1, buildResult.ResultByTarget.Count);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Target1"]);

            // Test the case when the scope contains partially correct data
            targets = new string[2]; targets[0] = "Target2"; targets[1] = "Target3";
            BuildRequest length2Request = new BuildRequest(1, "test.proj", targets, new BuildPropertyGroup(), null, 1, true, false);
            Assert.IsNull(cacheManager.GetCachedBuildResult(length2Request, out actuallyBuiltTargets), "Expect a null return value if partial data in the scope");
            
            // Test the correctness case for multiple targets
            cacheEntry = new BuildResultCacheEntry("Target3", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            buildResult = cacheManager.GetCachedBuildResult(length2Request, out actuallyBuiltTargets);
            Assert.IsNotNull(buildResult, "Expect a cached value if scope contains data");

            Assert.AreEqual(2, actuallyBuiltTargets.Count);
            Assert.AreEqual("Target2", actuallyBuiltTargets[0]);
            Assert.AreEqual("Target3", actuallyBuiltTargets[1]);
            Assert.AreEqual(2, buildResult.ResultByTarget.Count);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Target2"]);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Target3"]);
            Assert.AreEqual(1, buildResult.ProjectId);
        }
Beispiel #13
0
        public void TestRequestCachingDefaultInitialTargets()
        {
            CacheManager cacheManager = new CacheManager("3.5");

            ArrayList actuallyBuiltTargets;
            CacheScope cacheScope = cacheManager.GetCacheScope("test.proj", new BuildPropertyGroup(), null, CacheContentType.BuildResults);
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.defaultTargetCacheName, "Target1;Target2"));
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.initialTargetCacheName, "Initial1"));
            cacheScope.AddCacheEntry(new PropertyCacheEntry(Constants.projectIdCacheName, "5"));
            
            CacheEntry cacheEntry = new BuildResultCacheEntry("Initial1", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            cacheEntry = new BuildResultCacheEntry("Target1", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), null, CacheContentType.BuildResults);
            cacheEntry = new BuildResultCacheEntry("Target2", null, false);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), "3.5", CacheContentType.BuildResults);
            cacheEntry = new BuildResultCacheEntry("Target3", null, true);
            cacheManager.SetCacheEntries(new CacheEntry[] { cacheEntry }, "test.proj", new BuildPropertyGroup(), null, CacheContentType.BuildResults);

            // Default target
            BuildRequest defaultRequest = new BuildRequest(1, "test.proj", null, new BuildPropertyGroup(), null, 1, true, false);
            BuildResult buildResult = cacheManager.GetCachedBuildResult(defaultRequest, out actuallyBuiltTargets);
            Assert.IsNotNull(buildResult, "Expect a cached value if scope contains data");

            Assert.AreEqual(3, actuallyBuiltTargets.Count);
            Assert.AreEqual("Initial1", actuallyBuiltTargets[0]);
            Assert.AreEqual("Target1", actuallyBuiltTargets[1]);
            Assert.AreEqual("Target2", actuallyBuiltTargets[2]);
            Assert.AreEqual(3, buildResult.ResultByTarget.Count);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Initial1"]);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Target1"]);
            Assert.AreEqual(Target.BuildState.CompletedUnsuccessfully, buildResult.ResultByTarget["Target2"]);
            Assert.AreEqual(false, buildResult.EvaluationResult);
            Assert.AreEqual(5, buildResult.ProjectId);

            // Specific target
            BuildRequest specificRequest = new BuildRequest(1, "test.proj", new string[] { "Target3" }, new BuildPropertyGroup(), null, 1, true, false);
            buildResult = cacheManager.GetCachedBuildResult(specificRequest, out actuallyBuiltTargets);
            Assert.IsNotNull(buildResult, "Expect a cached value if scope contains data");

            Assert.AreEqual(2, actuallyBuiltTargets.Count);
            Assert.AreEqual("Initial1", actuallyBuiltTargets[0]);
            Assert.AreEqual("Target3", actuallyBuiltTargets[1]);
            Assert.AreEqual(2, buildResult.ResultByTarget.Count);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Initial1"]);
            Assert.AreEqual(Target.BuildState.CompletedSuccessfully, buildResult.ResultByTarget["Target3"]);
            Assert.AreEqual(true, buildResult.EvaluationResult);
            Assert.AreEqual(5, buildResult.ProjectId);
        }
Beispiel #14
0
        /// <summary>
        /// This method adds cached results for each target results for which are contained inside
        /// the build result. This method is thread safe.
        /// </summary>
        internal void AddCacheEntryForBuildResults(BuildResult buildResult)
        {
            ErrorUtilities.VerifyThrow(buildResult != null, "Expect a non-null build result");

            // Don't cache results if they are marked as uncacheable 
            if (!buildResult.UseResultCache)
            {
                return;
            }

            cacheScopeReaderWriterLock.AcquireWriterLock(Timeout.Infinite);

            try
            {
                if (!ContainsCacheEntry(Constants.defaultTargetCacheName))
                {
                    // If the project file is malformed the build may fail without initializing the initialtargets or
                    // the default targests fields. The retrieval code expects non-null values
                    // so it is necessary to replace null with empty string
                    ErrorUtilities.VerifyThrow(buildResult.EvaluationResult == false || buildResult.InitialTargets != null 
                                               && buildResult.DefaultTargets != null , 
                                               "Expect initial targets to be non-null for successful builds");
                    string defaultTargets = buildResult.DefaultTargets == null ? String.Empty : buildResult.DefaultTargets;
                    PropertyCacheEntry defaultTargetsCacheEntry = new PropertyCacheEntry(Constants.defaultTargetCacheName, defaultTargets);
                    AddCacheEntryInternal(defaultTargetsCacheEntry);

                    string initialTargets = buildResult.InitialTargets == null ? String.Empty : buildResult.InitialTargets;
                    PropertyCacheEntry initialTargetsCacheEntry = new PropertyCacheEntry(Constants.initialTargetCacheName, initialTargets );
                    AddCacheEntryInternal(initialTargetsCacheEntry);
                }

                if (!ContainsCacheEntry(Constants.projectIdCacheName))
                {
                    PropertyCacheEntry projectIdCacheEntry = new PropertyCacheEntry(Constants.projectIdCacheName, buildResult.ProjectId.ToString(CultureInfo.InvariantCulture));
                    AddCacheEntryInternal(projectIdCacheEntry);
                }

                IDictionary outputsByTargetName = buildResult.OutputsByTarget;

                //Create single entry for each target in the request
                foreach (DictionaryEntry entry in buildResult.ResultByTarget)
                {
                    Target.BuildState buildState = (Target.BuildState)entry.Value;

                    // Only cache successful and failed targets
                    if ((buildState == Target.BuildState.CompletedSuccessfully) ||
                        (buildState == Target.BuildState.CompletedUnsuccessfully))
                    {
                        BuildItem[] targetOutputs = null;

                        // Only cache output items for successful targets
                        if (buildState == Target.BuildState.CompletedSuccessfully)
                        {
                            ErrorUtilities.VerifyThrow(buildResult.OutputsByTarget.Contains(entry.Key),
                                "We must have build results for successful targets");

                            BuildItem[] outputItems = (BuildItem[])buildResult.OutputsByTarget[entry.Key];

                            // It's essential that we clear out any pointers to the project from the BuildItem;
                            // otherwise the cache will hold onto the project, and not save any memory.
                            if (outputItems != null)
                            {
                                for (int i = 0; i < outputItems.Length; i++)
                                {
                                    outputItems[i] = outputItems[i].VirtualClone(true /* remove references to minimise transitive size */);
                                }
                            }

                            targetOutputs = (BuildItem[])buildResult.OutputsByTarget[entry.Key];
                        }

                        BuildResultCacheEntry cacheEntry = new BuildResultCacheEntry((string)entry.Key, targetOutputs,
                            (buildState == Target.BuildState.CompletedSuccessfully));

                        if (Engine.debugMode)
                        {
                            Console.WriteLine("+++Adding cache entry for " + (string)entry.Key + " in " +
                                this.ScopeName + " result: " + (buildState == Target.BuildState.CompletedSuccessfully));
                        }

                        AddCacheEntryInternal(cacheEntry);
                    }
                }
            }
            finally
            {
                cacheScopeReaderWriterLock.ReleaseWriterLock();
            }
        }