From 74265b31c7af7058352cad0440acbeb11666603b Mon Sep 17 00:00:00 2001 From: Erik Kuefler Date: Thu, 27 Aug 2015 11:26:04 +0000 Subject: Basic groovy_test support -- Change-Id: I11d65bcacbb4a2037e29c6b3af7c4ff545636738 Reviewed-on: https://bazel-review.googlesource.com/#/c/1830/1 MOS_MIGRATED_REVID=101669018 --- tools/build_defs/groovy/README.md | 120 ++++++++++++++++++++++++++----- tools/build_defs/groovy/groovy.WORKSPACE | 24 +++++-- tools/build_defs/groovy/groovy.bzl | 60 +++++++++++++++- 3 files changed, 179 insertions(+), 25 deletions(-) (limited to 'tools') diff --git a/tools/build_defs/groovy/README.md b/tools/build_defs/groovy/README.md index e881a15510..a4d42cef4b 100644 --- a/tools/build_defs/groovy/README.md +++ b/tools/build_defs/groovy/README.md @@ -16,10 +16,11 @@ libraries and vice-versa. ## Setup -To be able to use the Groovy rules, you must make the Groovy binaries available -to Bazel. The easiest way to do so is by copying the content of -`groovy.WORKSPACE` to your workspace file and putting `groovy.BUILD` at the root -or your workspace. +To be able to use the Groovy rules, you must make the Groovy libraries and +binaries available to Bazel. Groovy tests also require JUnit and Hamcrest to be +available at a known location. The easiest way to do so is by copying the +content of `groovy.WORKSPACE` to your workspace file and putting `groovy.BUILD` +at the root of your workspace. ## Basic Example @@ -30,16 +31,22 @@ application: ``` [workspace]/ WORKSPACE - app/ - BUILD - GroovyApp.groovy - lib/ - BUILD - GroovyLib.groovy - JavaLib.java + src/main/groovy/ + app/ + BUILD + GroovyApp.groovy + lib/ + BUILD + GroovyLib.groovy + JavaLib.java + src/test/groovy/ + lib/ + BUILD + LibTest.groovy ``` -Then, to build the code under lib/, your `lib/BUILD` can look like this: +Then, to build the code under src/main/groovy/lib/, your +`src/main/groovy/lib/BUILD` can look like this: ```python load("/tools/build_rules/groovy/groovy", "groovy_library") @@ -60,8 +67,8 @@ java_library( For simplicity, you can combine Groovy and Java sources into a single library using `groovy_and_java_library`. Note that this allows the Groovy code to -reference the Java code, but not vice-versa. Your `lib/BUILD` file would then -look like this: +reference the Java code, but not vice-versa. Your `src/main/groovy/lib/BUILD` +file would then look like this: ```python load("/tools/build_rules/groovy/groovy", "groovy_and_java_library") @@ -72,7 +79,8 @@ groovy_and_java_library( ) ``` -Finally, you can define a binary using `groovy_binary` as follows: +To build the application under src/main/groovy/app, you can define a binary using +`groovy_binary` as follows: ```python load("/tools/build_rules/groovy/groovy", "groovy_binary") @@ -82,13 +90,32 @@ groovy_binary( srcs = glob(["*.groovy"]), main_class = "GroovyApp", deps = [ - "//lib", + "//src/main/groovy/lib", ], ) ``` -You can then build the application with `bazel build //app:GroovyApp` and run it -with `bazel run //app:GroovyApp`. +Finally, you can write tests in Groovy using `groovy_test`. The `srcs` of this +rule will be converted into names of class files that are passed to JUnit. For +this to work, the test sources must be under src/test/groovy or src/test/java. +To build the test under src/test/groovy/lib, your BUILD file would look like +this: + +```python +load("/tools/build_defs/groovy/groovy", "groovy_test", "groovy_library") + + +groovy_library( + name = "testlib", + srcs = glob(["*.groovy"]), +) + +groovy_test( + name = "LibTest", + srcs = ["LibTest.groovy"], + deps = [":testlib"], +) +``` ## Build Rule Reference [reference] @@ -267,3 +294,60 @@ with `bazel run //app:GroovyApp`. + + +### `groovy_test` + +`groovy_binary(name, main_class, srcs, deps, **kwargs)` + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescription
name + Name, required +

A unique name for this rule.

+
srcs + List of labels, required +

+ List of .groovy source files whose names will be converted to classes + passed to JUnitCore. +

+
deps + List of labels or .jar files, optional +

+ List of libraries to be included on both the compile-time classpath + when building this test and on the runtime classpath when executing it. +

+

+ These can be `groovy_library` targets, `java_library` targets, + `groovy_and_java_library` targets, or raw .jar files. +

+
jvm_flags + List of strings, optional +

+ A list of flags to embed in the wrapper script generated for running + this binary. +

+
diff --git a/tools/build_defs/groovy/groovy.WORKSPACE b/tools/build_defs/groovy/groovy.WORKSPACE index 8fce2532b1..ce196ba013 100644 --- a/tools/build_defs/groovy/groovy.WORKSPACE +++ b/tools/build_defs/groovy/groovy.WORKSPACE @@ -1,11 +1,27 @@ new_http_archive( - name = "groovy", + name = "groovy-bin", url = "http://dl.bintray.com/groovy/maven/apache-groovy-binary-2.4.4.zip", sha256 = "a7cc1e5315a14ea38db1b2b9ce0792e35174161141a6a3e2ef49b7b2788c258c", build_file = "tools/build_defs/groovy/groovy.BUILD", ) -bind( - name = "groovy/groovyc", - actual = "@groovy//:groovyc", +maven_jar( + name = "groovy", + group_id = "org.codehaus.groovy", + artifact_id = "groovy-all", + version = "2.3.7", ) + +maven_jar( + name = "hamcrest", + group_id = "org.hamcrest", + artifact_id = "hamcrest-core", + version = "1.3", +) + +maven_jar( + name = "junit", + group_id = "junit", + artifact_id = "junit", + version = "4.12", +) \ No newline at end of file diff --git a/tools/build_defs/groovy/groovy.bzl b/tools/build_defs/groovy/groovy.bzl index f435890e9d..3b65b8d707 100644 --- a/tools/build_defs/groovy/groovy.bzl +++ b/tools/build_defs/groovy/groovy.bzl @@ -29,9 +29,9 @@ def _groovy_jar_impl(ctx): # Compile all files in srcs with groovyc cmd = "rm -rf %s; mkdir -p %s\n" % (build_output, build_output) - cmd += "%s -cp %s -d %s %s\n" % ( + cmd += "%s %s -d %s %s\n" % ( ctx.file._groovyc.short_path, - ":".join([dep.path for dep in all_deps]), + "-cp " + ":".join([dep.path for dep in all_deps]) if len(all_deps) != 0 else "", build_output, " ".join([src.path for src in ctx.files.srcs]), ) @@ -70,7 +70,7 @@ _groovy_jar = rule( mandatory=False, allow_files=FileType([".jar"])), "_groovyc": attr.label( - default=Label("//external:groovy/groovyc"), + default=Label("@groovy-bin//:groovyc"), single_file=True), "_jar": attr.label( default=Label("//third_party/ijar:zipper"), @@ -155,3 +155,57 @@ def groovy_binary(name, main_class, srcs=[], deps=[], **kwargs): runtime_deps = all_deps, **kwargs ) + +def path_to_class(path): + if path.startswith("src/test/groovy/"): + return path[len("src/test/groovy/") : path.index(".groovy")].replace('/', '.') + elif path.startswith("src/test/java/"): + return path[len("src/test/java/") : path.index(".groovy")].replace('/', '.') + else: + fail("groovy_test sources must be under src/test/java or src/test/groovy") + +def groovy_test_impl(ctx): + # Extract all transitive dependencies + all_deps = set(ctx.files.deps + ctx.files._implicit_deps) + for this_dep in ctx.attr.deps: + if hasattr(this_dep, 'java'): + all_deps += this_dep.java.transitive_runtime_deps + + # Infer a class name from each src file + classes = [path_to_class(src.path) for src in ctx.files.srcs] + + # Write a file that executes JUnit on the inferred classes + cmd = "%s %s -cp %s org.junit.runner.JUnitCore %s\n" % ( + ctx.executable._java.path, + " ".join(ctx.attr.jvm_flags), + ":".join([dep.short_path for dep in all_deps]), + " ".join(classes), + ) + ctx.file_action( + output = ctx.outputs.executable, + content = cmd + ) + + # Return all dependencies needed to run the tests + return struct( + runfiles=ctx.runfiles(files=list(all_deps) + ctx.files._java), + ) + +groovy_test = rule( + implementation = groovy_test_impl, + attrs = { + "srcs": attr.label_list(mandatory=True, allow_files=FileType([".groovy"])), + "deps": attr.label_list(allow_files=FileType([".jar"])), + "jvm_flags": attr.string_list(), + "_java": attr.label( + default=Label("@local-jdk//:java"), + executable=True, + single_file=True), + "_implicit_deps": attr.label_list(default=[ + Label("@groovy//jar"), + Label("@hamcrest//jar"), + Label("@junit//jar"), + ]), + }, + test = True, +) -- cgit v1.2.3