From 38ed2cfdb588d2f04a9ce7c4bc352f26c534935d Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Sat, 9 Apr 2016 16:24:16 -0700
Subject: [PATCH] teach run_tests how to run C# tests with NUnitLite

---
 tools/run_tests/post_tests_csharp.bat         | 21 ++++++
 .../{run_csharp.sh => post_tests_csharp.sh}   | 27 +++-----
 tools/run_tests/run_csharp.bat                | 30 --------
 tools/run_tests/run_tests.py                  | 69 ++++++++++---------
 4 files changed, 67 insertions(+), 80 deletions(-)
 create mode 100644 tools/run_tests/post_tests_csharp.bat
 rename tools/run_tests/{run_csharp.sh => post_tests_csharp.sh} (68%)
 delete mode 100644 tools/run_tests/run_csharp.bat

diff --git a/tools/run_tests/post_tests_csharp.bat b/tools/run_tests/post_tests_csharp.bat
new file mode 100644
index 0000000000..a3137aafa1
--- /dev/null
+++ b/tools/run_tests/post_tests_csharp.bat
@@ -0,0 +1,21 @@
+@rem Runs C# tests for given assembly from command line. The Grpc.sln solution needs to be built before running the tests.
+
+setlocal
+
+@rem enter src/csharp directory
+cd /d %~dp0\..\..\src\csharp
+
+@rem Generate code coverage report
+@rem TODO(jtattermusch): currently the report list is hardcoded
+packages\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe -reports:"coverage_csharp_*.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
+
+@rem Generate the index.html file
+echo ^<html^>^<head^>^</head^>^<body^>^<a href='csharp_coverage/index.htm'^>csharp coverage^</a^>^<br/^>^</body^>^</html^> >..\..\reports\index.html
+
+endlocal
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/tools/run_tests/run_csharp.sh b/tools/run_tests/post_tests_csharp.sh
similarity index 68%
rename from tools/run_tests/run_csharp.sh
rename to tools/run_tests/post_tests_csharp.sh
index 7ba21d460e..bb6f5c6e18 100755
--- a/tools/run_tests/run_csharp.sh
+++ b/tools/run_tests/post_tests_csharp.sh
@@ -30,26 +30,15 @@
 
 set -ex
 
-CONFIG=${CONFIG:-opt}
-NUNIT_CONSOLE="mono packages/NUnit.ConsoleRunner.3.2.0/tools/nunit3-console.exe"
-
-# nunit3-console fails if nunit.framework.dll is not found.
-cp -n src/csharp/packages/NUnit.3.2.0/lib/net45/nunit.framework.dll src/csharp/packages/NUnit.ConsoleRunner.3.2.0/tools/
+if [ "$CONFIG" != "gcov" ] ; then exit ; fi
 
 # change to gRPC repo root
 cd $(dirname $0)/../..
 
-(cd src/csharp; $NUNIT_CONSOLE $@)
-
-if [ "$CONFIG" = "gcov" ]
-then
-  # Generate the csharp extension coverage report
-  gcov objs/gcov/src/csharp/ext/*.o
-  lcov --base-directory . --directory . -c -o coverage.info
-  lcov -e coverage.info '**/src/csharp/ext/*' -o coverage.info
-  genhtml -o reports/csharp_ext_coverage --num-spaces 2 \
-    -t 'gRPC C# native extension test coverage' coverage.info \
-    --rc genhtml_hi_limit=95 --rc genhtml_med_limit=80 --no-prefix
-fi
-
-
+# Generate the csharp extension coverage report
+gcov objs/gcov/src/csharp/ext/*.o
+lcov --base-directory . --directory . -c -o coverage.info
+lcov -e coverage.info '**/src/csharp/ext/*' -o coverage.info
+genhtml -o reports/csharp_ext_coverage --num-spaces 2 \
+  -t 'gRPC C# native extension test coverage' coverage.info \
+  --rc genhtml_hi_limit=95 --rc genhtml_med_limit=80 --no-prefix
diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat
deleted file mode 100644
index 025ec03472..0000000000
--- a/tools/run_tests/run_csharp.bat
+++ /dev/null
@@ -1,30 +0,0 @@
-@rem Runs C# tests for given assembly from command line. The Grpc.sln solution needs to be built before running the tests.
-
-setlocal
-
-@rem enter src/csharp directory
-cd /d %~dp0\..\..\src\csharp
-
-rem nunit3-console fails if nunit.framework.dll is not found.
-copy packages\NUnit.3.2.0\lib\net45\nunit.framework.dll packages\NUnit.ConsoleRunner.3.2.0\tools\nunit.framework.dll
-
-if not "%CONFIG%" == "gcov" (
-  packages\NUnit.ConsoleRunner.3.2.0\tools\nunit3-console.exe %* || goto :error
-) else (
-  @rem Run all tests with code coverage
-
-  packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -target:"packages\NUnit.ConsoleRunner.3.2.0\tools\nunit3-console.exe" -targetdir:"." -targetargs:"%*" -filter:"+[Grpc.Core]*"  -register:user -output:coverage_results.xml || goto :error
-
-  packages\ReportGenerator.2.4.4.0\tools\ReportGenerator.exe -reports:"coverage_results.xml" -targetdir:"..\..\reports\csharp_coverage" -reporttypes:"Html;TextSummary" || goto :error
-
-  @rem Generate the index.html file
-  echo ^<html^>^<head^>^</head^>^<body^>^<a href='csharp_coverage/index.htm'^>csharp coverage^</a^>^<br/^>^</body^>^</html^> >..\..\reports\index.html
-)
-
-endlocal
-
-goto :EOF
-
-:error
-echo Failed!
-exit /b %errorlevel%
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 4f3aaca7ec..e2cc3bdfff 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -486,42 +486,46 @@ class CSharpLanguage(object):
 
   def test_specs(self):
     with open('src/csharp/tests.json') as f:
-      tests_json = json.load(f)
-    assemblies = tests_json['assemblies']
-    tests = tests_json['tests']
+      tests_by_assembly = json.load(f)
 
     msbuild_config = _MSBUILD_CONFIG[self.config.build_config]
-    assembly_files = ['%s/bin/%s/%s.dll' % (a, msbuild_config, a)
-                      for a in assemblies]
-
-    # TODO(jtattermusch): use --x86 when needed
-
-    extra_args = ['--labels=All',
+    nunit_args = ['--labels=All',
                   '--noresult',
-                  '--workers=1',
-                  '--inprocess'] + assembly_files
-
+                  '--workers=1']
     if self.platform == 'windows':
-      script_name = 'tools\\run_tests\\run_csharp.bat'
-      extra_args += ['--domain=None']
+      runtime_cmd = []
     else:
-      script_name = 'tools/run_tests/run_csharp.sh'
-
-    if self.config.build_config == 'gcov':
-      # On Windows, we only collect C# code coverage.
-      # On Linux, we only collect coverage for native extension.
-      # For code coverage all tests need to run as one suite.
-      return [self.config.job_spec([script_name] + extra_args, None,
-                                    shortname='csharp.coverage',
-                                    environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
-    else:
-      specs = []
-      for test in tests:
-        cmdline = [script_name, '--test=%s' % test] + extra_args
-        specs.append(self.config.job_spec(cmdline, None,
-                                          shortname='csharp.%s' % test,
+      runtime_cmd = ['mono']
+
+    specs = []
+    for assembly in tests_by_assembly.iterkeys():
+      assembly_file = 'src/csharp/%s/bin/%s/%s.exe' % (assembly, msbuild_config, assembly)
+      if self.config.build_config != 'gcov':
+        # normally, run each test as a separate process
+        for test in tests_by_assembly[assembly]:
+          cmdline = runtime_cmd + [assembly_file, '--test=%s' % test] + nunit_args
+          specs.append(self.config.job_spec(cmdline,
+                                            None,
+                                            shortname='csharp.%s' % test,
+                                            environ=_FORCE_ENVIRON_FOR_WRAPPERS))
+      else:
+        # for test coverage, run all tests from the same assembly at once
+        # on Windows, things get more complicated as we need to run the code coverage tool
+        if self.platform == 'windows':
+          cmdline = ['packages\OpenCover.4.6.519\tools\OpenCover.Console.exe',
+                     '-target:%s' % assembly_file,
+                     '-targetdir:src\\csharp',
+                     '-targetargs:%s' % ' '.join(nunit_args),
+                     '-filter:+[Grpc.Core]*',
+                     '-register:user',
+                     '-output:coverage_csharp_%s.xml' % assembly]
+        else:
+          cmdline = runtime_cmd + [assembly_file] + nunit_args
+
+        specs.append(self.config.job_spec([script_name] + extra_args, None,
+                                          shortname='csharp.coverage.%s' % assembly,
                                           environ=_FORCE_ENVIRON_FOR_WRAPPERS))
-      return specs
+    return specs
 
   def pre_build_steps(self):
     if self.platform == 'windows':
@@ -544,7 +548,10 @@ class CSharpLanguage(object):
       return [['tools/run_tests/build_csharp.sh']]
 
   def post_tests_steps(self):
-    return []
+    if self.platform == 'windows':
+      return [['tools\\run_tests\\post_tests_csharp.bat']]
+    else:
+      return [['tools/run_tests/post_tests_csharp.sh']]
 
   def makefile_name(self):
     return 'Makefile'
-- 
GitLab