Esempio n. 1
0
        public void MetadataPropertyFunctionBug()
        {
            const string prefix         = "SomeLongPrefix-"; // Needs to be longer than "%(FileName)"
            var          projectContent = $@"
<Project>
  <ItemGroup>
    <Bar Include=`{prefix}foo`>
      <Baz>$([System.String]::new(%(FileName)).Substring({prefix.Length}))</Baz>
    </Bar>
  </ItemGroup>
</Project>
".Cleanup();

            var items = ObjectModelHelpers.GetItems(projectContent, allItems: true);

            var expectedMetadata = new[]
            {
                new Dictionary <string, string>
                {
                    { "Baz", "foo" },
                },
            };

            ObjectModelHelpers.AssertItems(new[] { $"{prefix}foo" }, items, expectedMetadata);
        }
Esempio n. 2
0
        public void IncludeShouldPreserveIntermediaryReferences()
        {
            var content = @"
                            <i2 Include='a;b;c'>
                                <m1>m1_contents</m1>
                                <m2>m2_contents</m2>
                            </i2>

                            <i Include='@(i2)'/>

                            <i2 Include='d;e;f'>
                                <m1>m1_updated</m1>
                                <m2>m2_updated</m2>
                            </i2>";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content);

            var expectedMetadata = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "m2_contents" },
            };

            ObjectModelHelpers.AssertItems(new [] { "a", "b", "c" }, items, expectedMetadata);
        }
Esempio n. 3
0
        public void ContextDisambiguatesAFullyQualifiedGlobPointingInAnotherRelativeGlobsCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var project1Directory     = _env.DefaultTestDirectory.CreateDirectory("Project1");
            var project1GlobDirectory = project1Directory.CreateDirectory("Glob").CreateDirectory("1").Path;

            var project2Directory = _env.DefaultTestDirectory.CreateDirectory("Project2");

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                // first project uses a relative path
                new ProjectSpecification(
                    Path.Combine(project1Directory.Path, "1"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("Glob", "**", "*.cs")}` />
                            </ItemGroup>
                        </Project>"),
                // second project reaches out into first project's cone via a fully qualified path
                new ProjectSpecification(
                    Path.Combine(project2Directory.Path, "2"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine(project1Directory.Path, "Glob", "**", "*.cs")}` />
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine("Glob", "1", i))
                                            .ToArray();

                // project 2 has fully qualified directory parts, so make the results for 2 fully qualified
                if (projectName.Equals("2"))
                {
                    expectedGlobExpansion = expectedGlobExpansion
                                            .Select(i => Path.Combine(project1Directory.Path, i))
                                            .ToArray();
                }

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(project1GlobDirectory, $"{evaluationCount}.cs"), "");
            }
                );
        }
Esempio n. 4
0
        public void ContextPinsGlobExpansionCache(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory = _env.DefaultTestDirectory.FolderPath;

            _env.SetCurrentDirectory(projectDirectory);

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                _globProjects,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        public void ContextDisambiguatesDistinctRelativeGlobsPointingOutsideOfSameProjectCone(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var globDirectory = _env.DefaultTestDirectory.CreateDirectory("glob");

            var projectRoot = _env.DefaultTestDirectory.CreateDirectory("proj");

            var project1Directory = projectRoot.CreateDirectory("Project1");

            var project2SubDir = projectRoot.CreateDirectory("subdirectory");

            var project2Directory = project2SubDir.CreateDirectory("Project2");

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(project1Directory.Path, "1"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../../glob/*.cs` />
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(project2Directory.Path, "2"),
                    @"<Project>
                            <ItemGroup>
                                <i Include=`../../../glob/*.cs` />
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName            = Path.GetFileNameWithoutExtension(project.FullPath);
                var globFixedDirectoryPart = projectName.EndsWith("1")
                        ? Path.Combine("..", "..", "glob")
                        : Path.Combine("..", "..", "..", "glob");

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine(globFixedDirectoryPart, i))
                                            .ToArray();

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");
            }
                );
        }
        private void ContextCachesCommonOutOfProjectCone(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var testDirectory = _env.DefaultTestDirectory;
            var globDirectory = testDirectory.CreateDirectory("GlobDirectory");

            var itemSpecDirectoryPart = itemSpecPathIsRelative
                ? Path.Combine("..", "GlobDirectory")
                : globDirectory.Path;

            Directory.CreateDirectory(globDirectory.Path);

            // Globs with a directory part will produce items prepended with that directory part
            foreach (var globExpansion in expectedGlobExpansions)
            {
                for (var i = 0; i < globExpansion.Length; i++)
                {
                    globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]);
                }
            }

            var projectSpecs = new[]
            {
                $@"<Project>
                <ItemGroup>
                    <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/>
                </ItemGroup>
            </Project>",
                $@"<Project>
                <ItemGroup>
                    <i Include=`{Path.Combine("{0}", "**", "*.cs")}`/>
                </ItemGroup>
            </Project>"
            }
            .Select(p => string.Format(p, itemSpecDirectoryPart))
            .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory.Path, $"ProjectDirectory{i}", $"Project{i}.proj"), p));

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                projectSpecs,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory.Path, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        public void ContextDisambiguatesSameRelativeGlobsPointingOutsideDifferentProjectCones(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var project1Root          = _env.DefaultTestDirectory.CreateDirectory("Project1");
            var project1Directory     = project1Root.CreateDirectory("1").Path;
            var project1GlobDirectory = project1Root.CreateDirectory("Glob").CreateDirectory("1").Path;

            var project2Root          = _env.DefaultTestDirectory.CreateDirectory("Project2");
            var project2Directory     = project2Root.CreateDirectory("2").Path;
            var project2GlobDirectory = project2Root.CreateDirectory("Glob").CreateDirectory("2").Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), "");
            File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(project1Directory, "1"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("..", "Glob", "**", "*.cs")}`/>
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(project2Directory, "2"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("..", "Glob", "**", "*.cs")}`/>
                            </ItemGroup>
                        </Project>")
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                // globs have the fixed directory part prepended, so add it to the expected results
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => Path.Combine("..", "Glob", projectName, $"{projectName}.{i}"))
                                            .ToArray();

                var actualGlobExpansion = project.GetItems("i");
                ObjectModelHelpers.AssertItems(expectedGlobExpansion, actualGlobExpansion);

                evaluationCount++;

                File.WriteAllText(Path.Combine(project1GlobDirectory, $"1.{evaluationCount}.cs"), "");
                File.WriteAllText(Path.Combine(project2GlobDirectory, $"2.{evaluationCount}.cs"), "");
            }
                );
        }
Esempio n. 8
0
        public void RemoveRespectsItemTransform()
        {
            var content = @"
                            <i Include='a;b;c' />

                            <i Remove='@(i->WithMetadataValue(`Identity`, `b`))' />
                            <i Remove='@(i->`%(Extension)`)' /> <!-- should do nothing -->";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content, allItems: true);

            ObjectModelHelpers.AssertItems(new[] { "a", "c" }, items);
        }
        public void MetadataAndPropertyReferencesGetExpandedInPropertyFunctionArgumentsInsideMetadataElements()
        {
            var projectContent =
                @"<Project>
        <ItemGroup>
            <A Include=`1` />
            <B Include=`B`>
               <M>$([System.String]::new(`%(Identity)`))</M>
               <M2>$([System.String]::new(`%(M)`))</M2>
            </B>
            <C Include=`C`>
               <M>$([System.String]::new(`$(P)`))</M>
               <M2>$([System.String]::new(`%(M)`))</M2>
            </C>
            <D Include=`D`>
               <M>$([System.String]::new(`@(A)`))</M>
               <M2>$([System.String]::new(`%(M)`))</M2>
            </D>
        </ItemGroup>

        <PropertyGroup>
            <P>@(A)</P>
        </PropertyGroup>
</Project>";

            var items = ObjectModelHelpers.GetItems(projectContent, allItems: true);

            var expectedMetadata = new[]
            {
                new Dictionary <string, string>(),
                new Dictionary <string, string>
                {
                    { "M", "B" },
                    { "M2", "B" }
                },
                new Dictionary <string, string>
                {
                    { "M", "@(A)" },
                    { "M2", "@(A)" }
                },
                new Dictionary <string, string>
                {
                    { "M", "@(A)" },
                    { "M2", "@(A)" }
                }
            };

            ObjectModelHelpers.AssertItems(new[] { "1", "B", "C", "D" }, items, expectedMetadata);
        }
Esempio n. 10
0
        public void UpdateShouldPreserveIntermediaryReferences()
        {
            var content = @"
                            <i2 Include='a;b;c'>
                                <m1>m1_contents</m1>
                                <m2>%(Identity)</m2>
                            </i2>

                            <i Include='@(i2)'>
                                <m3>@(i2 -> '%(m2)')</m3>
                                <m4 Condition=""'@(i2 -> '%(m2)')' == 'a;b;c'"">m4_contents</m4>
                            </i>

                            <i2 Update='a;b;c'>
                                <m1>m1_updated</m1>
                                <m2>m2_updated</m2>
                                <m3>m3_updated</m3>
                                <m4>m4_updated</m4>
                            </i2>";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content);

            var a = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "a" },
                { "m3", "a;b;c" },
                { "m4", "m4_contents" },
            };

            var b = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "b" },
                { "m3", "a;b;c" },
                { "m4", "m4_contents" }
            };

            var c = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "c" },
                { "m3", "a;b;c" },
                { "m4", "m4_contents" },
            };

            ObjectModelHelpers.AssertItems(new[] { "a", "b", "c" }, items, new [] { a, b, c });
        }
        public void ContextDisambiguatesSameRelativeGlobsPointingInsideDifferentProjectCones(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory1 = _env.DefaultTestDirectory.CreateDirectory("1").Path;
            var projectDirectory2 = _env.DefaultTestDirectory.CreateDirectory("2").Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), "");
            File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), "");

            EvaluateProjects(
                new []
            {
                new ProjectSpecification(
                    Path.Combine(projectDirectory1, "1"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("**", "*.cs")}` />
                            </ItemGroup>
                        </Project>"),
                new ProjectSpecification(
                    Path.Combine(projectDirectory2, "2"),
                    $@"<Project>
                            <ItemGroup>
                                <i Include=`{Path.Combine("**", "*.cs")}` />
                            </ItemGroup>
                        </Project>"),
            },
                context,
                project =>
            {
                var projectName = Path.GetFileNameWithoutExtension(project.FullPath);

                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount]
                                            .Select(i => $"{projectName}.{i}")
                                            .ToArray();

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));

                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory1, $"1.{evaluationCount}.cs"), "");
                File.WriteAllText(Path.Combine(projectDirectory2, $"2.{evaluationCount}.cs"), "");
            }
                );
        }
        // projects should cache glob expansions when the glob is shared between projects and points outside of project cone
        public void ContextCachesCommonOutOfProjectConeGlob(bool itemSpecPathIsRelative, EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var testDirectory = _env.DefaultTestDirectory.FolderPath;
            var globDirectory = Path.Combine(testDirectory, "GlobDirectory");

            var itemSpecDirectoryPart = itemSpecPathIsRelative
                ? Path.Combine("..", "GlobDirectory")
                : globDirectory;

            itemSpecDirectoryPart = itemSpecDirectoryPart.WithTrailingSlash();

            Directory.CreateDirectory(globDirectory);

            // Globs with a directory part will produce items prepended with that directory part
            foreach (var globExpansion in expectedGlobExpansions)
            {
                for (var i = 0; i < globExpansion.Length; i++)
                {
                    globExpansion[i] = Path.Combine(itemSpecDirectoryPart, globExpansion[i]);
                }
            }

            var projectSpecs = _projectsWithOutOfConeGlobs
                               .Select(p => string.Format(p, itemSpecDirectoryPart))
                               .Select((p, i) => new ProjectSpecification(Path.Combine(testDirectory, $"ProjectDirectory{i}", $"Project{i}.proj"), p));

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), "");

            EvaluateProjects(
                projectSpecs,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(globDirectory, $"{evaluationCount}.cs"), "");

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        public void RemoveShouldPreserveIntermediaryReferences(string content)
        {
            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content, allItems: true);

            var expectedMetadata = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "m2_contents" }
            };

            var itemsForI = items.Where(i => i.ItemType == "i").ToList();

            ObjectModelHelpers.AssertItems(new[] { "a", "b", "c" }, itemsForI, expectedMetadata);

            var itemsForI2 = items.Where(i => i.ItemType == "i2").ToList();

            ObjectModelHelpers.AssertItems(new string[0], itemsForI2);
        }
        public void ExcludeSeesIntermediaryState()
        {
            var projectContent =
                @"<Project>
  <ItemGroup>
    <a Include=`1` />
    <i Include=`1;2` Exclude=`@(a)` />
    <a Include=`2` />
    <a Condition=`'@(a)' == '1;2'` Include=`3` />
  </ItemGroup>
  <Target Name=`Build`>
    <Message Text=`Done!` />
  </Target>
</Project>";

            var items = ObjectModelHelpers.GetItems(projectContent);

            ObjectModelHelpers.AssertItems(new [] { "2" }, items);
        }
        public void OnlyPropertyReferencesGetExpandedInPropertyFunctionArgumentsInsideIncludeAttributes()
        {
            var projectContent =
                @"<Project>
        <ItemGroup>
            <A Include=`1`/>
            <B Include=`$([System.String]::new('@(A)'))`/>
            <C Include=`$([System.String]::new('$(P)'))`/>
        </ItemGroup>

        <PropertyGroup>
            <P>@(A)</P>
        </PropertyGroup>
</Project>";

            var items = ObjectModelHelpers.GetItems(projectContent, allItems: true);

            ObjectModelHelpers.AssertItems(new[] { "1", "@(A)", "@(A)" }, items);
        }
        public void IncludeShouldPreserveIntermediaryReferences()
        {
            var content = @"
                            <i2 Include='a;b;c'>
                                <m1>m1_contents</m1>
                                <m2>m2_contents</m2>
                            </i2>

                            <i Include='@(i2)'/>

                            <i2 Include='d;e;f;@(i2)'>
                                <m1>m1_updated</m1>
                                <m2>m2_updated</m2>
                            </i2>";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content, allItems: true);

            var mI2_1 = new Dictionary <string, string>
            {
                { "m1", "m1_contents" },
                { "m2", "m2_contents" },
            };

            var itemsForI = items.Where(i => i.ItemType == "i").ToList();

            ObjectModelHelpers.AssertItems(new [] { "a", "b", "c" }, itemsForI, mI2_1);

            var mI2_2 = new Dictionary <string, string>
            {
                { "m1", "m1_updated" },
                { "m2", "m2_updated" },
            };

            var itemsForI2 = items.Where(i => i.ItemType == "i2").ToList();

            ObjectModelHelpers.AssertItems(
                new[] { "a", "b", "c", "d", "e", "f", "a", "b", "c" },
                itemsForI2,
                new [] { mI2_1, mI2_1, mI2_1, mI2_2, mI2_2, mI2_2, mI2_2, mI2_2, mI2_2 });
        }
Esempio n. 17
0
        public void UpdateRespectsItemTransform()
        {
            var content = @"
                            <i Include='a;b;c' />

                            <i Update='@(i->WithMetadataValue(`Identity`, `b`))'>
                                <m1>m1_updated</m1>
                            </i>
                            <i Update=`@(i->'%(Extension)')`> <!-- should do nothing -->
                                <m2>m2_updated</m2>
                            </i>";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content, allItems: true);

            ObjectModelHelpers.AssertItems(new[] { "a", "b", "c" }, items,
                                           new[] {
                new Dictionary <string, string>(),
                new Dictionary <string, string> {
                    ["m1"] = "m1_updated"
                },
                new Dictionary <string, string>(),
            });
        }
        public void ContextCachesImportGlobExpansions(EvaluationContext.SharingPolicy policy, string[][] expectedGlobExpansions)
        {
            var projectDirectory = _env.DefaultTestDirectory.Path;

            var context = EvaluationContext.Create(policy);

            var evaluationCount = 0;

            File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup());

            EvaluateProjects(
                _projectsWithGlobImports,
                context,
                project =>
            {
                var expectedGlobExpansion = expectedGlobExpansions[evaluationCount];
                evaluationCount++;

                File.WriteAllText(Path.Combine(projectDirectory, $"{evaluationCount}.props"), $"<Project><ItemGroup><i Include=`{evaluationCount}.cs`/></ItemGroup></Project>".Cleanup());

                ObjectModelHelpers.AssertItems(expectedGlobExpansion, project.GetItems("i"));
            }
                );
        }
        public void ItemOperationsShouldExpandIndirectItemReferences(string projectContent, string[] expectedItemValues, Dictionary <string, string> expectedItemMetadata)
        {
            var items = ObjectModelHelpers.GetItems(projectContent);

            ObjectModelHelpers.AssertItems(expectedItemValues, items, expectedItemMetadata);
        }
        public void MultipleInterItemDependenciesOnSameItemOperation()
        {
            var content = @"
                            <i1 Include='i1_1;i1_2;i1_3;i1_4;i1_5'/>
                            <i1 Update='*'>
                                <m>i1</m>
                            </i1>
                            <i1 Remove='*i1_5'/>

                            <i_cond Condition='@(i1->Count()) == 4' Include='i1 has 4 items'/>

                            <i2 Include='@(i1);i2_4'/>
                            <i2 Remove='i?_4'/>
                            <i2 Update='i?_1'>
                               <m>i2</m>
                            </i2>

                            <i3 Include='@(i1);i3_3'/>
                            <i3 Remove='*i?_3'/>

                            <i1 Remove='*i1_2'/>
                            <i1 Include='i1_6'/>";

            IList <ProjectItem> items = ObjectModelHelpers.GetItemsFromFragment(content, allItems: true);

            var i1BaseMetadata = new Dictionary <string, string>
            {
                { "m", "i1" }
            };

            //i1 items: i1_1; i1_3; i1_4; i1_6
            var i1Metadata = new Dictionary <string, string>[]
            {
                i1BaseMetadata,
                i1BaseMetadata,
                i1BaseMetadata,
                new Dictionary <string, string>()
            };

            var i1Items = items.Where(i => i.ItemType == "i1").ToList();

            ObjectModelHelpers.AssertItems(new[] { "i1_1", "i1_3", "i1_4", "i1_6" }, i1Items, i1Metadata);

            //i2 items: i1_1; i1_2; i1_3
            var i2Metadata = new Dictionary <string, string>[]
            {
                new Dictionary <string, string>
                {
                    { "m", "i2" }
                },
                i1BaseMetadata,
                i1BaseMetadata
            };

            var i2Items = items.Where(i => i.ItemType == "i2").ToList();

            ObjectModelHelpers.AssertItems(new[] { "i1_1", "i1_2", "i1_3" }, i2Items, i2Metadata);

            //i3 items: i1_1; i1_2; i1_4
            var i3Items = items.Where(i => i.ItemType == "i3").ToList();

            ObjectModelHelpers.AssertItems(new[] { "i1_1", "i1_2", "i1_4" }, i3Items, i1BaseMetadata);

            var i_condItems = items.Where(i => i.ItemType == "i_cond").ToList();

            ObjectModelHelpers.AssertItems(new[] { "i1 has 4 items" }, i_condItems);
        }