Example #1
0
        /// <summary>
        /// Main “driver” method of all the tests. Contains common housekeeping code. All tests must call it.
        /// </summary>
        /// <remarks>
        ///   <para>
        ///     The <paramref name="runner"/> parameter is an action which is passed the following arguments, in
        ///     the order of declaration:
        ///   </para>
        ///   <para>
        ///     <list type="bullet">
        ///        <item>
        ///          <term>TestProjectInfo testInfo</term>
        ///          <description>Information about the location of all the project files and directories</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>bool many</term>
        ///          <description>whether the test is building more than 20 layouts to test parallel builds</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>bool dtb</term>
        ///          <description>whether the test is running a design time build (DTB)</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>LocalBuilder builder</term>
        ///          <description>the object that runs the actual build session</description>
        ///        </item>
        ///     </list>
        ///   </para>
        /// </remarks>
        /// <param name="testName">Name of the test being run. Must be unique</param>
        /// <param name="many">Generate code in parallel if <c>true</c>, serially otherwise</param>
        /// <param name="dtb">Test design-time build if <c>true</c>, regular build otherwise</param>
        /// <param name="runner">Action consituting the main body of the test. Passed parameters are described above in the remarks section.</param>
        void RunTest(string testName, bool many, bool dtb, Action <TestProjectInfo, bool, bool, LocalBuilder> runner)
        {
            string       temporaryProjectDir = PrepareProject(testName);
            LocalBuilder builder             = GetBuilder($"{ProjectName}.{testName}");

            builder.BuildingInsideVisualStudio = dtb;
            var testInfo = new TestProjectInfo(ProjectName, testName, temporaryProjectDir, TestOutputDir);

            try {
                runner(testInfo, many, dtb, builder);

                if (many)
                {
                    Assert.That(WasParsedInParallel(testInfo), Is.True, "Should have been parsed in parallel");
                    Assert.That(WasGeneratedInParallel(testInfo), Is.True, "Should have been generated in parallel");
                }
                else
                {
                    Assert.That(WasParsedInParallel(testInfo), Is.False, "Should have been parsed in serial manner");
                    Assert.That(WasGeneratedInParallel(testInfo), Is.False, "Should have been generated in serial manner");
                }
            } catch {
                CopyLogs(testInfo, false);
                throw;
            }
        }
Example #2
0
        void SuccessfulBuild_RunTest(TestProjectInfo testInfo, bool many, bool dtb, LocalBuilder builder)
        {
            string[] parameters = GetBuildProperties(many, dtb);
            bool     success    = builder.Build(testInfo.SlnPath, GetBuildTarget(dtb), parameters);

            CopyLogs(testInfo, true);
            Assert.That(success, Is.True, "Build should have succeeded");

            CopyGeneratedFiles(testInfo);

            foreach (SourceFile src in generated_sources)
            {
                foreach (SourceFileMember member in src)
                {
                    string generatedFile = Path.Combine(testInfo.GeneratedPath, src.Path);
                    if (member.IsMethod)
                    {
                        Assert.That(SourceHasMethod(generatedFile, member.Visibility, member.Type, member.Name, member.Arguments), Is.True, $"Method {member.Name} must exist in {generatedFile}");
                    }
                    else
                    {
                        Assert.That(SourceHasProperty(generatedFile, member.Visibility, member.Type, member.Name, member.IsExpressionBody), Is.True, $"Property {member.Name} must exist in {generatedFile}");
                    }
                }
            }

            if (dtb)
            {
                return;                 // DTB doesn't produce binaries
            }
            foreach (string binaryName in produced_binaries)
            {
                AssertExists(testInfo.TestName, Path.Combine(testInfo.BinPath, binaryName));
            }
        }
Example #3
0
        /// <summary>
        /// Main “driver” method of all the tests. Contains common housekeeping code. All tests must call it.
        /// </summary>
        /// <remarks>
        ///   <para>
        ///     The <paramref name="runner"/> parameter is an action which is passed the following arguments, in
        ///     the order of declaration:
        ///   </para>
        ///   <para>
        ///     <list type="bullet">
        ///        <item>
        ///          <term>TestProjectInfo testInfo</term>
        ///          <description>Information about the location of all the project files and directories</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>bool many</term>
        ///          <description>whether the test is building more than 20 layouts to test parallel builds</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>bool dtb</term>
        ///          <description>whether the test is running a design time build (DTB)</description>
        ///        </item>
        ///
        ///        <item>
        ///          <term>LocalBuilder builder</term>
        ///          <description>the object that runs the actual build session</description>
        ///        </item>
        ///     </list>
        ///   </para>
        /// </remarks>
        /// <param name="testName">Name of the test being run. Must be unique</param>
        /// <param name="many">Generate code in parallel if <c>true</c>, serially otherwise</param>
        /// <param name="dtb">Test design-time build if <c>true</c>, regular build otherwise</param>
        /// <param name="runner">Action consituting the main body of the test. Passed parameters are described above in the remarks section.</param>
        void RunTest(string testName, bool many, bool dtb, Action <TestProjectInfo, bool, bool, LocalBuilder> runner)
        {
            string       temporaryProjectDir = PrepareProject(testName);
            LocalBuilder builder             = GetBuilder($"{ProjectName}.{testName}");

            builder.BuildingInsideVisualStudio = dtb;
            var testInfo = new TestProjectInfo(ProjectName, testName, temporaryProjectDir, TestOutputDir);

            try {
                runner(testInfo, many, dtb, builder);

                if (many)
                {
                    Assert.That(WasParsedInParallel(testInfo), Is.True, "Should have been parsed in parallel");
                    Assert.That(WasGeneratedInParallel(testInfo), Is.True, "Should have been generated in parallel");
                }
                else
                {
                    Assert.That(WasParsedInParallel(testInfo), Is.False, "Should have been parsed in serial manner");
                    Assert.That(WasGeneratedInParallel(testInfo), Is.False, "Should have been generated in serial manner");
                }
            } catch {
                CopyLogs(testInfo, false);
                foreach (var file in Directory.GetFiles(testInfo.OutputDirectory, "*.log", SearchOption.AllDirectories))
                {
                    TestContext.AddTestAttachment(file);
                }
                throw;
            }

            // Clean up successful tests
            FileSystemUtils.SetDirectoryWriteable(testInfo.OutputDirectory);
            Directory.Delete(testInfo.OutputDirectory, recursive: true);
        }
Example #4
0
 void CopyLogs(TestProjectInfo testInfo, bool assert)
 {
     AssertExistsAndCopy(testInfo, GetTestLogName(testInfo), testInfo.OutputDirectory, assert);
     foreach (string log in log_files)
     {
         AssertExistsAndCopy(testInfo, log, testInfo.OutputDirectory, assert);
     }
 }
Example #5
0
        void CopyGeneratedFiles(TestProjectInfo testInfo)
        {
            string destDir = Path.Combine(testInfo.OutputDirectory, "generated");

            foreach (SourceFile src in generated_sources)
            {
                AssertExistsAndCopy(testInfo, Path.Combine(testInfo.GeneratedPath, src.Path), destDir);
            }
        }
Example #6
0
        void FailedBuild_ConflictingRelativeLayout_RunTest(TestProjectInfo testInfo, bool many, bool dtb, LocalBuilder builder)
        {
            string[] parameters = GetBuildProperties(many, dtb, "NOT_CONFLICTING_RELATIVELAYOUT");
            bool     success    = builder.Build(testInfo.SlnPath, GetBuildTarget(dtb), parameters);

            CopyLogs(testInfo, true);
            Assert.That(success, Is.False, "Build should have failed");

            string logPath   = GetTestLogPath(testInfo);
            bool   haveError = HaveCompilerError_CS0266(logPath, "OnboardingActivityPartial.cs", 43, "Android.Views.View", "Android.Widget.RelativeLayout");

            AssertHaveCompilerError(haveError, "OnboardingActivityPartial.cs", 43);

            haveError = HaveCompilerError_CS0266(logPath, "OnboardingActivity.cs", 38, "Android.Views.View", "Android.Widget.RelativeLayout");
            AssertHaveCompilerError(haveError, "OnboardingActivity.cs", 38);
        }
Example #7
0
        void FailedBuild_ConflictingFragment_RunTest(TestProjectInfo testInfo, bool many, bool dtb, LocalBuilder builder)
        {
            string[] parameters = GetBuildProperties(many, dtb, "NOT_CONFLICTING_FRAGMENT");
            bool     success    = builder.Build(testInfo.SlnPath, GetBuildTarget(dtb), parameters);

            CopyLogs(testInfo, true);
            Assert.That(success, Is.False, "Build should have failed");

            string logPath   = GetTestLogPath(testInfo);
            bool   haveError = HaveCompilerError_CS0266(logPath, "MainActivity.cs", 26, "Android.App.Fragment", "CommonSampleLibrary.LogFragment");

            AssertHaveCompilerError(haveError, "MainActivity.cs", 26);

            haveError = HaveCompilerError_CS0266(logPath, "AnotherMainActivity.cs", 23, "Android.App.Fragment", "CommonSampleLibrary.LogFragment");
            AssertHaveCompilerError(haveError, "AnotherMainActivity.cs", 23);
        }
Example #8
0
        void AssertExistsAndCopy(TestProjectInfo testInfo, string relativeFilePath, string destDir, bool nunitAssert = true)
        {
            string source = Path.Combine(testInfo.RootDirectory, relativeFilePath);

            if (nunitAssert)
            {
                AssertExists(testInfo.TestName, source);
            }
            else if (!File.Exists(source))
            {
                return;
            }

            if (!Directory.Exists(destDir))
            {
                Directory.CreateDirectory(destDir);
            }
            string destination = Path.Combine(destDir, Path.GetFileName(relativeFilePath));

            File.Copy(source, destination, true);
        }
Example #9
0
 string GetTestLogPath(TestProjectInfo testInfo)
 {
     return(Path.Combine(testInfo.RootDirectory, GetTestLogName(testInfo)));
 }
Example #10
0
 string GetTestLogName(TestProjectInfo testInfo)
 {
     return($"{testInfo.ProjectName}.{testInfo.TestName}.log");
 }
Example #11
0
        bool WasGeneratedInParallel(TestProjectInfo testInfo)
        {
            var regex = new Regex($"^\\s*Generating binding code in parallel.*$", RegexOptions.Compiled);

            return(FileMatches(regex, GetTestLogPath(testInfo)));
        }
Example #12
0
        bool WasParsedInParallel(TestProjectInfo testInfo)
        {
            var regex = new Regex($"^\\s*Parsing layouts in parallel.*$", RegexOptions.Compiled);

            return(FileMatches(regex, GetTestLogPath(testInfo)));
        }