diff --git a/MODULE.bazel b/MODULE.bazel index 03fce0c..4150050 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,6 +24,9 @@ maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") maven.install( name = "rules_android_lint_deps", artifacts = [ + # Testing + "org.assertj:assertj-core:3.24.2", + "junit:junit:4.13.2", # Worker Dependencies # TODO(bencodes) Remove these and use the worker impl. that Bazel defines internally "com.squareup.moshi:moshi:1.15.0", diff --git a/rules/BUILD.bazel b/rules/BUILD.bazel index d3f5f63..ab4af5d 100644 --- a/rules/BUILD.bazel +++ b/rules/BUILD.bazel @@ -35,11 +35,17 @@ bzl_library( srcs = ["defs.bzl"], visibility = ["//visibility:public"], deps = [ - "//rules/private:collect_aar_outputs_aspect", + ":collect_aar_outputs_aspect", "@bazel_skylib//lib:dicts", ], ) +bzl_library( + name = "collect_aar_outputs_aspect", + srcs = ["collect_aar_outputs_aspect.bzl"], + visibility = ["//visibility:public"], +) + bzl_library( name = "extensions", srcs = ["extensions.bzl"], @@ -52,9 +58,3 @@ bzl_library( srcs = ["toolchain.bzl"], visibility = ["//visibility:public"], ) - -py_binary( - name = "test_runner_executable", - srcs = ["test_runner_executable.py"], - visibility = ["//visibility:public"], -) diff --git a/rules/collect_aar_outputs_aspect.bzl b/rules/collect_aar_outputs_aspect.bzl index 8f02348..854f251 100644 --- a/rules/collect_aar_outputs_aspect.bzl +++ b/rules/collect_aar_outputs_aspect.bzl @@ -1,10 +1,3 @@ -"""Aspect that collects the AAR outputs. - -Lint needs access to the raw archived aar outputs. This aspect collects them all from the dependences, -exports, and associates of the target. It then wraps them up in an AndroidLintAARInfo provider so that -Lint targets have access to them. -""" - AndroidLintAARInfo = provider( "A provider to collect all aars from transitive dependencies", fields = { diff --git a/rules/defs.bzl b/rules/defs.bzl index 6b7ba0c..1a708f7 100644 --- a/rules/defs.bzl +++ b/rules/defs.bzl @@ -3,7 +3,7 @@ load( _dicts = "dicts", ) load( - "//rules/private:collect_aar_outputs_aspect.bzl", + "//rules:collect_aar_outputs_aspect.bzl", _AndroidLintAARInfo = "AndroidLintAARInfo", _collect_aar_outputs_aspect = "collect_aar_outputs_aspect", ) @@ -27,12 +27,12 @@ _AUTOMATIC_EXEC_GROUPS_ENABLED = dict( _ATTRS = dict( _lint_wrapper = attr.label( - default = "//rules/private/cli:lint_wrapper", + default = "//src/cli:cli", executable = True, cfg = "exec", ), _test_runner_executable = attr.label( - default = "//rules:test_runner_executable", + default = "//src:test_runner_executable", executable = True, cfg = "exec", ), diff --git a/rules/private/BUILD.bazel b/rules/private/BUILD.bazel deleted file mode 100644 index 58e111c..0000000 --- a/rules/private/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -bzl_library( - name = "collect_aar_outputs_aspect", - srcs = ["collect_aar_outputs_aspect.bzl"], - visibility = ["//visibility:public"], -) diff --git a/rules/private/collect_aar_outputs_aspect.bzl b/rules/private/collect_aar_outputs_aspect.bzl deleted file mode 100644 index 854f251..0000000 --- a/rules/private/collect_aar_outputs_aspect.bzl +++ /dev/null @@ -1,34 +0,0 @@ -AndroidLintAARInfo = provider( - "A provider to collect all aars from transitive dependencies", - fields = { - "aars": "depset of aars", - }, -) - -def _collect_aar_outputs_aspect(_, ctx): - deps = getattr(ctx.rule.attr, "deps", []) - exports = getattr(ctx.rule.attr, "exports", []) - associates = getattr(ctx.rule.attr, "associates", []) - transitive_aar_depsets = [] - for dep in deps + exports + associates: - if AndroidLintAARInfo in dep: - transitive_aar_depsets.append(dep[AndroidLintAARInfo].aars) - - direct_aars = None - if hasattr(ctx.rule.attr, "aar"): - aar = ctx.rule.attr.aar.files.to_list()[0] - direct_aars = [aar] - - return [ - AndroidLintAARInfo( - aars = depset( - direct = direct_aars, - transitive = transitive_aar_depsets, - ), - ), - ] - -collect_aar_outputs_aspect = aspect( - implementation = _collect_aar_outputs_aspect, - attr_aspects = ["aar", "deps", "exports", "associates"], -) diff --git a/src/BUILD.bazel b/src/BUILD.bazel new file mode 100644 index 0000000..2b392ce --- /dev/null +++ b/src/BUILD.bazel @@ -0,0 +1,5 @@ +py_binary( + name = "test_runner_executable", + srcs = ["test_runner_executable.py"], + visibility = ["//visibility:public"], +) diff --git a/rules/private/cli/AndroidLintAction.kt b/src/cli/AndroidLintAction.kt similarity index 100% rename from rules/private/cli/AndroidLintAction.kt rename to src/cli/AndroidLintAction.kt diff --git a/rules/private/cli/AndroidLintActionArgs.kt b/src/cli/AndroidLintActionArgs.kt similarity index 100% rename from rules/private/cli/AndroidLintActionArgs.kt rename to src/cli/AndroidLintActionArgs.kt diff --git a/rules/private/cli/AndroidLintBaselineSanitizer.kt b/src/cli/AndroidLintBaselineSanitizer.kt similarity index 100% rename from rules/private/cli/AndroidLintBaselineSanitizer.kt rename to src/cli/AndroidLintBaselineSanitizer.kt diff --git a/rules/private/cli/AndroidLintProject.kt b/src/cli/AndroidLintProject.kt similarity index 100% rename from rules/private/cli/AndroidLintProject.kt rename to src/cli/AndroidLintProject.kt diff --git a/rules/private/cli/AndroidLintRunner.kt b/src/cli/AndroidLintRunner.kt similarity index 100% rename from rules/private/cli/AndroidLintRunner.kt rename to src/cli/AndroidLintRunner.kt diff --git a/rules/private/cli/AndroidLintWrapperUtils.kt b/src/cli/AndroidLintWrapperUtils.kt similarity index 100% rename from rules/private/cli/AndroidLintWrapperUtils.kt rename to src/cli/AndroidLintWrapperUtils.kt diff --git a/rules/private/cli/BUILD b/src/cli/BUILD similarity index 94% rename from rules/private/cli/BUILD rename to src/cli/BUILD index 8b1ca6b..f397f2b 100644 --- a/rules/private/cli/BUILD +++ b/src/cli/BUILD @@ -3,12 +3,26 @@ load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") load("@rules_kotlin//kotlin:lint.bzl", "ktlint_fix", "ktlint_test") java_binary( - name = "lint_wrapper", + name = "cli", main_class = "com.rules.android.lint.cli.AndroidLintAction", visibility = ["//visibility:public"], runtime_deps = [":lint"], ) +kt_jvm_library( + name = "lint", + srcs = glob(["*.kt"]), + visibility = ["//visibility:public"], + deps = [ + "//src/worker", + "@rules_android_lint_deps//:com_android_tools_lint_lint", + "@rules_android_lint_deps//:com_android_tools_lint_lint_api", + "@rules_android_lint_deps//:com_android_tools_lint_lint_checks", + "@rules_android_lint_deps//:com_android_tools_lint_lint_model", + "@rules_android_lint_deps//:com_xenomachina_kotlin_argparser", + ], +) + ktlint_test( name = "lint_ktlint_test", srcs = glob(["*.kt"]), @@ -22,17 +36,3 @@ ktlint_fix( config = "//:editorconfig", visibility = ["//visibility:private"], ) - -kt_jvm_library( - name = "lint", - srcs = glob(["*.kt"]), - visibility = ["//visibility:public"], - deps = [ - "//rules/private/worker", - "@rules_android_lint_deps//:com_android_tools_lint_lint", - "@rules_android_lint_deps//:com_android_tools_lint_lint_api", - "@rules_android_lint_deps//:com_android_tools_lint_lint_checks", - "@rules_android_lint_deps//:com_android_tools_lint_lint_model", - "@rules_android_lint_deps//:com_xenomachina_kotlin_argparser", - ], -) diff --git a/rules/test_runner_executable.py b/src/test_runner_executable.py similarity index 100% rename from rules/test_runner_executable.py rename to src/test_runner_executable.py diff --git a/rules/private/worker/BUILD b/src/worker/BUILD similarity index 100% rename from rules/private/worker/BUILD rename to src/worker/BUILD diff --git a/rules/private/worker/InvocationWorker.kt b/src/worker/InvocationWorker.kt similarity index 100% rename from rules/private/worker/InvocationWorker.kt rename to src/worker/InvocationWorker.kt diff --git a/rules/private/worker/PersistentWorker.kt b/src/worker/PersistentWorker.kt similarity index 100% rename from rules/private/worker/PersistentWorker.kt rename to src/worker/PersistentWorker.kt diff --git a/rules/private/worker/PersistentWorkerCpuTimeBasedGcScheduler.kt b/src/worker/PersistentWorkerCpuTimeBasedGcScheduler.kt similarity index 100% rename from rules/private/worker/PersistentWorkerCpuTimeBasedGcScheduler.kt rename to src/worker/PersistentWorkerCpuTimeBasedGcScheduler.kt diff --git a/rules/private/worker/WorkRequest.kt b/src/worker/WorkRequest.kt similarity index 100% rename from rules/private/worker/WorkRequest.kt rename to src/worker/WorkRequest.kt diff --git a/rules/private/worker/WorkResponse.kt b/src/worker/WorkResponse.kt similarity index 100% rename from rules/private/worker/WorkResponse.kt rename to src/worker/WorkResponse.kt diff --git a/rules/private/worker/Worker.kt b/src/worker/Worker.kt similarity index 100% rename from rules/private/worker/Worker.kt rename to src/worker/Worker.kt diff --git a/rules/private/worker/WorkerIO.kt b/src/worker/WorkerIO.kt similarity index 100% rename from rules/private/worker/WorkerIO.kt rename to src/worker/WorkerIO.kt diff --git a/rules/private/worker/WorkerJsonMessageProcessor.kt b/src/worker/WorkerJsonMessageProcessor.kt similarity index 100% rename from rules/private/worker/WorkerJsonMessageProcessor.kt rename to src/worker/WorkerJsonMessageProcessor.kt diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index 6fba512..602c6be 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -6,7 +6,7 @@ test_suite( name = "tests", tests = [ ":versions_test", - "//tests/private/cli:tests", - "//tests/private/worker:tests", + "//tests/src/cli:tests", + "//tests/src/worker:tests", ], ) diff --git a/tests/private/cli/BUILD b/tests/private/cli/BUILD deleted file mode 100644 index e0cfdc1..0000000 --- a/tests/private/cli/BUILD +++ /dev/null @@ -1,6 +0,0 @@ -load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") -load("@rules_kotlin//kotlin:lint.bzl", "ktlint_fix", "ktlint_test") - -test_suite( - name = "tests", -) diff --git a/tests/private/worker/BUILD b/tests/private/worker/BUILD deleted file mode 100644 index e0cfdc1..0000000 --- a/tests/private/worker/BUILD +++ /dev/null @@ -1,6 +0,0 @@ -load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") -load("@rules_kotlin//kotlin:lint.bzl", "ktlint_fix", "ktlint_test") - -test_suite( - name = "tests", -) diff --git a/tests/src/cli/AndroidLintActionArgsTest.kt b/tests/src/cli/AndroidLintActionArgsTest.kt new file mode 100644 index 0000000..fe2ceb0 --- /dev/null +++ b/tests/src/cli/AndroidLintActionArgsTest.kt @@ -0,0 +1,76 @@ +package com.rules.android.lint.cli + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import java.nio.file.Paths + +@RunWith(JUnit4::class) +class AndroidLintActionArgsTest { + + @Test + fun `does parse all arguments`() { + val parseArgs = AndroidLintActionArgs.parseArgs( + args = listOf( + "--module-name", + "test_module_name", + "--label", + "test", + "--src", + "path/to/Foo.kt", + "--output", + "output.jar", + "--project-config-output", + "project.xml", + "--resource", + "path/to/resource/strings.xml", + "--android-manifest", + "AndroidManifest.xml", + "--baseline-file", + "lib_lint_baseline.xml", + "--config-file", + "lint_config.xml", + "--custom-rule", + "custom_rule.jar", + "--classpath", + "classpath.jar", + "--classpath", + "classpath.aar", + "--autofix", + "--regenerate-baseline-files", + "--warnings-as-errors", + "--enable-check", + "custom-check", + "--disable-check", + "custom-disabled-check", + "--compile-sdk-version", + "1.6", + "--java-language-level", + "1.7", + "--kotlin-language-level", + "1.8", + ), + ) + + assertThat(parseArgs.moduleName).isEqualTo("test_module_name") + assertThat(parseArgs.label).isEqualTo("test") + assertThat(parseArgs.srcs).containsExactly(Paths.get("path/to/Foo.kt")) + assertThat(parseArgs.output).isEqualTo(Paths.get("output.jar")) + assertThat(parseArgs.projectConfigOutput).isEqualTo(Paths.get("project.xml")) + assertThat(parseArgs.resources).containsExactly(Paths.get("path/to/resource/strings.xml")) + assertThat(parseArgs.baselineFile).isEqualTo(Paths.get("lib_lint_baseline.xml")) + assertThat(parseArgs.config).isEqualTo(Paths.get("lint_config.xml")) + assertThat(parseArgs.customChecks).containsExactly(Paths.get("custom_rule.jar")) + assertThat(parseArgs.classpath) + .containsExactly(Paths.get("classpath.jar"), Paths.get("classpath.aar")) + assertThat(parseArgs.autofix).isTrue + assertThat(parseArgs.regenerateBaselineFile).isTrue + assertThat(parseArgs.warningsAsErrors).isTrue + assertThat(parseArgs.enableChecks).containsExactly("custom-check") + assertThat(parseArgs.disableChecks).containsExactly("custom-disabled-check") + assertThat(parseArgs.compileSdkVersion).isEqualTo("1.6") + assertThat(parseArgs.javaLanguageLevel).isEqualTo("1.7") + assertThat(parseArgs.kotlinLanguageLevel).isEqualTo("1.8") + } +} diff --git a/tests/src/cli/AndroidLintActionTest.kt b/tests/src/cli/AndroidLintActionTest.kt new file mode 100644 index 0000000..e891def --- /dev/null +++ b/tests/src/cli/AndroidLintActionTest.kt @@ -0,0 +1,13 @@ +package com.rules.android.lint.cli + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class AndroidLintActionTest { + @Test + fun `empty test case`() { + // TODO(bencodes) Add some tests for AndroidLintAction + } +} diff --git a/tests/src/cli/AndroidLintProjectTest.kt b/tests/src/cli/AndroidLintProjectTest.kt new file mode 100644 index 0000000..3fbe89d --- /dev/null +++ b/tests/src/cli/AndroidLintProjectTest.kt @@ -0,0 +1,56 @@ +package com.rules.android.lint.cli + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import java.nio.file.Path + +@RunWith(JUnit4::class) +class AndroidLintProjectTest { + + @Rule + @JvmField + var tmpDirectory = TemporaryFolder() + + private fun TemporaryFolder.newPath(name: String): Path = this.newFile(name).toPath() + + @Test + fun `test asXMLString does produce correct project file content`() { + assertThat( + createProjectXMLString( + moduleName = "test_module_name", + srcs = listOf(tmpDirectory.newPath("Foo.kt")), + resources = listOf(tmpDirectory.newPath("foo.xml")), + androidManifest = tmpDirectory.newPath("AndroidManifest.xml"), + classpathJars = listOf(tmpDirectory.newPath("Foo.jar")), + classpathAars = listOf(tmpDirectory.newPath("Foo.aar")), + classpathExtractedAarDirectories = listOf( + Pair( + tmpDirectory.newPath("Bar.aar"), + tmpDirectory.newFolder("tmp/unpacked_aars/bar/").toPath(), + ), + ), + customLintChecks = listOf(tmpDirectory.newPath("tmp/unpacked_aars/bar/lint.jar")), + ), + ).isEqualTo( + """ + + + + + + + + + + + + + + """.trimIndent().replace("{root}", tmpDirectory.root.absolutePath), + ) + } +} diff --git a/tests/src/cli/BUILD b/tests/src/cli/BUILD new file mode 100644 index 0000000..c2196ea --- /dev/null +++ b/tests/src/cli/BUILD @@ -0,0 +1,58 @@ +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") +load("@rules_kotlin//kotlin:lint.bzl", "ktlint_fix", "ktlint_test") + +kt_jvm_test( + name = "AndroidLintActionArgsTest", + srcs = ["AndroidLintActionArgsTest.kt"], + associates = ["//src/cli:lint"], + test_class = "com.rules.android.lint.cli.AndroidLintActionArgsTest", + deps = [ + "@rules_android_lint_deps//:junit_junit", + "@rules_android_lint_deps//:org_assertj_assertj_core", + ], +) + +kt_jvm_test( + name = "AndroidLintActionTest", + srcs = ["AndroidLintActionTest.kt"], + associates = ["//src/cli:lint"], + test_class = "com.rules.android.lint.cli.AndroidLintActionTest", + deps = [ + "@rules_android_lint_deps//:junit_junit", + "@rules_android_lint_deps//:org_assertj_assertj_core", + ], +) + +kt_jvm_test( + name = "AndroidLintProjectTest", + srcs = ["AndroidLintProjectTest.kt"], + associates = ["//src/cli:lint"], + test_class = "com.rules.android.lint.cli.AndroidLintProjectTest", + deps = [ + "@rules_android_lint_deps//:junit_junit", + "@rules_android_lint_deps//:org_assertj_assertj_core", + ], +) + +ktlint_test( + name = "lint_ktlint_test", + srcs = glob(["*.kt"]), + config = "//:editorconfig", + visibility = ["//visibility:private"], +) + +ktlint_fix( + name = "lint_ktlint_fix", + srcs = glob(["*.kt"]), + config = "//:editorconfig", + visibility = ["//visibility:private"], +) + +test_suite( + name = "tests", + tests = [ + ":AndroidLintActionArgsTest", + ":AndroidLintActionTest", + ":AndroidLintProjectTest", + ], +) diff --git a/tests/src/worker/BUILD b/tests/src/worker/BUILD new file mode 100644 index 0000000..1f69beb --- /dev/null +++ b/tests/src/worker/BUILD @@ -0,0 +1,32 @@ +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") +load("@rules_kotlin//kotlin:lint.bzl", "ktlint_fix", "ktlint_test") + +kt_jvm_test( + name = "WorkerIOTest", + srcs = ["WorkerIOTest.kt"], + associates = ["//src/worker"], + test_class = "com.rules.android.lint.worker.WorkerIOTest", + deps = [ + "@rules_android_lint_deps//:junit_junit", + "@rules_android_lint_deps//:org_assertj_assertj_core", + ], +) + +kt_jvm_test( + name = "WorkerJsonMessageProcessorTest", + srcs = ["WorkerJsonMessageProcessorTest.kt"], + associates = ["//src/worker"], + test_class = "com.rules.android.lint.worker.WorkerJsonMessageProcessorTest", + deps = [ + "@rules_android_lint_deps//:junit_junit", + "@rules_android_lint_deps//:org_assertj_assertj_core", + ], +) + +test_suite( + name = "tests", + tests = [ + ":WorkerIOTest", + ":WorkerJsonMessageProcessorTest", + ], +) diff --git a/tests/src/worker/WorkerIOTest.kt b/tests/src/worker/WorkerIOTest.kt new file mode 100644 index 0000000..a5e86a1 --- /dev/null +++ b/tests/src/worker/WorkerIOTest.kt @@ -0,0 +1,97 @@ +package com.rules.android.lint.worker + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.PrintStream +import java.nio.charset.StandardCharsets + +@RunWith(JUnit4::class) +class WorkerIOTest { + + @Test + @Throws(Exception::class) + fun testWorkerIO_doesWrapSystemStreams() { + // Save the original streams + val originalInputStream = System.`in` + val originalOutputStream = System.out + val originalErrorStream = System.err + + // Swap in the test streams to assert against + val byteArrayInputStream = ByteArrayInputStream(ByteArray(0)) + val outputBuffer = PrintStream(ByteArrayOutputStream(), true) + val errorBuffer = PrintStream(ByteArrayOutputStream(), true) + System.setIn(byteArrayInputStream) + System.setOut(outputBuffer) + System.setErr(errorBuffer) + + try { + WorkerIO().use { io -> + // Redirect the system streams + io.redirectSystemStreams() + + // Assert that the WorkerIO returns the correct wrapped streams and the System instance + // has been swapped out with the wrapped one. System.in should be untouched. + assertThat(System.`in`).isSameAs(byteArrayInputStream) + + assertThat(io.output).isSameAs(outputBuffer) + assertThat(System.out).isSameAs(errorBuffer) + + assertThat(io.err).isSameAs(errorBuffer) + assertThat(System.err).isSameAs(errorBuffer) + } + } finally { + // Swap back in the original streams + System.setIn(originalInputStream) + System.setOut(originalOutputStream) + System.setErr(originalErrorStream) + + outputBuffer.close() + errorBuffer.close() + byteArrayInputStream.close() + } + } + + @Test + @Throws(Exception::class) + fun testWorkerIO_doesWriteSystemOutToSystemError() { + // Save the original streams + val originalInputStream = System.`in` + val originalOutputStream = System.out + val originalErrorStream = System.err + + // Swap in the test streams to assert against + val byteArrayInputStream = ByteArrayInputStream(ByteArray(0)) + val byteArrayOutputStream = ByteArrayOutputStream() + val outputBuffer = PrintStream(byteArrayOutputStream, true) + System.setIn(byteArrayInputStream) + System.setOut(outputBuffer) + System.setErr(outputBuffer) + try { + WorkerIO().use { io -> + // Redirect the system streams + io.redirectSystemStreams() + var captured = String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8) + assertThat(captured).isEmpty() + + // Assert that the standard out/error stream redirect to our own streams + println("This is a standard out message!") + System.err.println("This is a standard error message!") + captured = String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8) + byteArrayOutputStream.reset() + assertThat(captured) + .isEqualTo("This is a standard out message!\nThis is a standard error message!\n") + } + } finally { + // Swap back in the original streams + System.setIn(originalInputStream) + System.setOut(originalOutputStream) + System.setErr(originalErrorStream) + outputBuffer.close() + byteArrayInputStream.close() + } + } +} diff --git a/tests/src/worker/WorkerJsonMessageProcessorTest.kt b/tests/src/worker/WorkerJsonMessageProcessorTest.kt new file mode 100644 index 0000000..170dc97 --- /dev/null +++ b/tests/src/worker/WorkerJsonMessageProcessorTest.kt @@ -0,0 +1,65 @@ +package com.rules.android.lint.worker + +import okio.Buffer +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.fail +import org.junit.After +import org.junit.Test + + +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4::class) +class WorkerJsonMessageProcessorTest { + + private val jsonBuffer = Buffer() + private val processor = WorkerJsonMessageProcessor( + inputStream = jsonBuffer.inputStream(), + outputStream = jsonBuffer.outputStream(), + ) + + @After + fun reset() { + jsonBuffer.close() + } + + @Test + fun doesEncodeWorkResponseJsonCorrectly() { + processor.writeWorkResponse(WorkResponse(requestId = 110, exitCode = 100, output = "foo")) + + val json = jsonBuffer.readString(Charsets.UTF_8) + assertThat(json).isEqualTo("{\"requestId\":110,\"exitCode\":100,\"output\":\"foo\"}") + } + + @Test + fun doesParseWorkRequestJsonCorrectly() { + jsonBuffer.writeString("{\"requestId\": 100, \"arguments\": [\"foo\"]}", Charsets.UTF_8) + + val workRequest = processor.readWorkRequest() + assertThat(workRequest).isNotNull + assertThat(workRequest.requestId).isEqualTo(100) + assertThat(workRequest.arguments).containsExactly("foo") + } + + @Test + fun doesDefaultRequestIDToZeroWhenNotPresent() { + jsonBuffer.writeString("{\"arguments\": []}", Charsets.UTF_8) + + val workRequest = processor.readWorkRequest() + assertThat(workRequest).isNotNull + assertThat(workRequest.requestId).isEqualTo(0) + } + + @Test + fun doesCrashWhenArgumentsNotPresent() { + jsonBuffer.writeString("{\"requestId\": 100}", Charsets.UTF_8) + + try { + processor.readWorkRequest() + fail("readNextWorkRequest is expected to fail when arguments not provided!") + } catch (e: Exception) { + assertThat(e).hasMessage("Required value 'arguments' missing at \$") + } + } +}