From cdda27ea3a4ed5f13c74a6b6836c20a9d435c2f6 Mon Sep 17 00:00:00 2001 From: JesseBrault0709 <62299747+JesseBrault0709@users.noreply.github.com> Date: Sun, 14 May 2023 15:44:07 +0200 Subject: [PATCH] Beginning to move logic from Runner to util methods in BuildScripts. --- .../ssg/buildscript/BuildScriptRunner.groovy | 3 + .../ssg/buildscript/BuildScripts.groovy | 79 ++++++++ .../ssg/buildscript/BuildScriptsTests.groovy | 191 ++++++++++++++++++ .../SimpleBuildScriptRunnerTests.groovy | 183 ----------------- 4 files changed, 273 insertions(+), 183 deletions(-) create mode 100644 api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScripts.groovy create mode 100644 api/src/test/groovy/com/jessebrault/ssg/buildscript/BuildScriptsTests.groovy delete mode 100644 api/src/test/groovy/com/jessebrault/ssg/buildscript/SimpleBuildScriptRunnerTests.groovy diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScriptRunner.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScriptRunner.groovy index 2b79f5f..a5fdfa0 100644 --- a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScriptRunner.groovy +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScriptRunner.groovy @@ -5,6 +5,9 @@ import groovy.transform.stc.SimpleType import java.util.function.Consumer +/** + * TODO: get rid of this, split it into two different classes/util functions (BuildScripts?) + */ interface BuildScriptRunner { Collection runBuildScript( diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScripts.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScripts.groovy new file mode 100644 index 0000000..cf65fac --- /dev/null +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildScripts.groovy @@ -0,0 +1,79 @@ +package com.jessebrault.ssg.buildscript + +import groovy.transform.stc.ClosureParams +import groovy.transform.stc.SimpleType +import org.codehaus.groovy.control.CompilerConfiguration + +import java.util.function.Consumer + +final class BuildScripts { + + private static Collection runBase(BuildScriptBase base) { + base.run() + BuildSpecUtil.getBuilds(base.getBuildSpecs()) + } + + static Collection runBuildScript( + @DelegatesTo(value = BuildScriptBase, strategy = Closure.DELEGATE_FIRST) + @ClosureParams(value = SimpleType, options = 'com.jessebrault.ssg.buildscript.BuildScriptBase') + Closure scriptBody + ) { + def base = new BuildScriptBase() { + + @Override + Object run() { + scriptBody.delegate = this + scriptBody.resolveStrategy = Closure.DELEGATE_FIRST + scriptBody.call(this) + } + + } + runBase(base) + } + + static Collection runBuildScript( + String scriptName, + URL scriptBaseDirUrl, + Collection otherUrls, + Map binding, + Consumer configureBuildScript + ) { + def engine = new GroovyScriptEngine([scriptBaseDirUrl, *otherUrls] as URL[]) + + engine.config = new CompilerConfiguration().tap { + scriptBaseClass = 'com.jessebrault.ssg.buildscript.BuildScriptBase' + } + + def base = engine.createScript(scriptName, new Binding(binding)) + assert base instanceof BuildScriptBase + configureBuildScript.accept(base) + runBase(base) + } + + static Collection runBuildScript( + String scriptName, + URL scriptBaseDirUrl, + Collection otherUrls, + Map binding + ) { + runBuildScript(scriptName, scriptBaseDirUrl, otherUrls, binding) { } + } + + static Collection runBuildScript( + String scriptName, + URL scriptBaseDirUrl, + Collection otherUrls + ) { + runBuildScript(scriptName, scriptBaseDirUrl, otherUrls, [:]) { } + } + + static Collection runBuildScript( + String scriptName, + URL scriptBaseDirUrl + ) { + runBuildScript(scriptName, scriptBaseDirUrl, [], [:]) { } + } + + private BuildScripts() {} + +} diff --git a/api/src/test/groovy/com/jessebrault/ssg/buildscript/BuildScriptsTests.groovy b/api/src/test/groovy/com/jessebrault/ssg/buildscript/BuildScriptsTests.groovy new file mode 100644 index 0000000..a12325b --- /dev/null +++ b/api/src/test/groovy/com/jessebrault/ssg/buildscript/BuildScriptsTests.groovy @@ -0,0 +1,191 @@ +package com.jessebrault.ssg.buildscript + +import com.jessebrault.ssg.SiteSpec +import groovy.transform.NullCheck +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension + +import java.util.function.Consumer +import java.util.function.Function + +import static com.jessebrault.ssg.buildscript.BuildScripts.runBuildScript +import static org.junit.jupiter.api.Assertions.assertEquals +import static org.mockito.Mockito.verify + +final class BuildScriptsTests { + + @NullCheck + @ExtendWith(MockitoExtension) + static final class ScriptFileTests { + + /** + * Must be non-static, otherwise Groovy gets confused inside the Closures. + * + * TODO: use the FileUtil.copyResourceToWriter method + */ + @SuppressWarnings('GrMethodMayBeStatic') + private void copyLocalResourceToWriter(String name, Writer target) { + BuildScriptsTests.getResourceAsStream(name).withReader { + it.transferTo(target) + } + } + + /** + * Must be non-static, otherwise Groovy gets confused inside the Closures. + */ + @SuppressWarnings('GrMethodMayBeStatic') + private File setupScripts(Collection resourceNames) { + def tempDir = File.createTempDir() + new FileTreeBuilder(tempDir).tap { + resourceNames.each { String resourceName -> + file(resourceName).withWriter { + this.copyLocalResourceToWriter(resourceName, it) + } + } + } + tempDir + } + + @Test + void simpleScript() { + def baseDir = this.setupScripts(['simple.groovy']) + def builds = runBuildScript('simple.groovy', baseDir.toURI().toURL()) + assertEquals(1, builds.size()) + assertEquals('test', builds[0].name) + } + + @Test + void testImport() { + def baseDir = this.setupScripts(['testImport.groovy', 'TestHtmlTask.groovy']) + def builds = runBuildScript('testImport.groovy', baseDir.toURI().toURL()) + assertEquals(1, builds.size()) + assertEquals('test', builds[0].name) + } + + @Test + void buildSrcTest() { + def baseDir = File.createTempDir() + new FileTreeBuilder(baseDir).tap { + file('buildSrcTest.groovy').withWriter { + this.copyLocalResourceToWriter('buildSrcTest.groovy', it) + } + dir('buildSrc') { + file('AnotherTask.groovy').withWriter { + this.copyLocalResourceToWriter('buildSrc/AnotherTask.groovy', it) + } + } + } + def builds = runBuildScript( + 'buildSrcTest.groovy', + baseDir.toURI().toURL(), + [new File(baseDir, 'buildSrc').toURI().toURL()] + ) + assertEquals(1, builds.size()) + assertEquals('test', builds[0].name) + } + + @Test + void withBinding(@Mock Consumer stringConsumer) { + def baseDir = this.setupScripts(['withBinding.groovy']) + runBuildScript( + 'withBinding.groovy', + baseDir.toURI().toURL(), + [], + [stringConsumer: stringConsumer] + ) + verify(stringConsumer).accept('test') + } + + } + + @ExtendWith(MockitoExtension) + static final class ClosureScriptTests { + + @Test + void simple() { + def result = runBuildScript { + build(name: 'test') { } + } + assertEquals(1, result.size()) + assertEquals('test', result[0].name) + } + + @Test + void oneBuildOutputDirWithFunction(@Mock Function mockOutputDirFunction) { + def r = runBuildScript { + build(name: 'test') { + outputDirFunction = mockOutputDirFunction + } + } + assertEquals(1, r.size()) + def b0 = r[0] + assertEquals(mockOutputDirFunction, b0.outputDirFunction) + } + + @Test + void oneBuildOutputDirWithFile() { + def f = new File('test') + def r = runBuildScript { + build(name: 'test') { + outputDir = f + } + } + assertEquals(1, r.size()) + def b0 = r[0] + assertEquals(f, b0.outputDirFunction.apply(b0) as File) + } + + @Test + void oneBuildOutputDirWithString() { + def r = runBuildScript { + build(name: 'test') { + outputDir = 'test' + } + } + assertEquals(1, r.size()) + def b0 = r[0] + assertEquals('test', b0.outputDirFunction.apply(b0) as String) + } + + @Test + void oneBuildSiteSpec() { + def r = runBuildScript { + build(name: 'test') { + siteSpec { + name = 'testSite' + baseUrl = 'https://testsite.com' + } + } + } + assertEquals(1, r.size()) + def b0 = r[0] + assertEquals(new SiteSpec('testSite', 'https://testsite.com'), b0.siteSpec) + } + + @Test + void oneBuildWithAbstractParent() { + def r = runBuildScript { + abstractBuild(name: 'parent') { + siteSpec { + name = 'Test Site' + baseUrl = 'https://test.com' + } + } + + build(name: 'child', extending: 'parent') { + siteSpec { base -> + baseUrl = base.baseUrl + '/child' + } + } + } + + assertEquals(1, r.size()) + def b0 = r[0] + assertEquals(new SiteSpec('Test Site', 'https://test.com/child'), b0.siteSpec) + } + + } + +} diff --git a/api/src/test/groovy/com/jessebrault/ssg/buildscript/SimpleBuildScriptRunnerTests.groovy b/api/src/test/groovy/com/jessebrault/ssg/buildscript/SimpleBuildScriptRunnerTests.groovy deleted file mode 100644 index 49882df..0000000 --- a/api/src/test/groovy/com/jessebrault/ssg/buildscript/SimpleBuildScriptRunnerTests.groovy +++ /dev/null @@ -1,183 +0,0 @@ -package com.jessebrault.ssg.buildscript - -import com.jessebrault.ssg.SiteSpec -import groovy.transform.NullCheck -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.Mock -import org.mockito.junit.jupiter.MockitoExtension - -import java.util.function.Consumer -import java.util.function.Function - -import static org.junit.jupiter.api.Assertions.assertEquals -import static org.mockito.Mockito.verify - -@NullCheck -@ExtendWith(MockitoExtension) -final class SimpleBuildScriptRunnerTests { - - private final BuildScriptRunner runner = new SimpleBuildScriptRunner() - - /** - * Must be non-static, otherwise Groovy gets confused inside the Closures. - * - * TODO: use the FileUtil.copyResourceToWriter method - */ - @SuppressWarnings('GrMethodMayBeStatic') - private void copyLocalResourceToWriter(String name, Writer target) { - SimpleBuildScriptRunnerTests.getResourceAsStream(name).withReader { - it.transferTo(target) - } - } - - /** - * Must be non-static, otherwise Groovy gets confused inside the Closures. - */ - @SuppressWarnings('GrMethodMayBeStatic') - private File setupScripts(Collection resourceNames) { - def tempDir = File.createTempDir() - new FileTreeBuilder(tempDir).tap { - resourceNames.each { String resourceName -> - file(resourceName).withWriter { - this.copyLocalResourceToWriter(resourceName, it) - } - } - } - tempDir - } - - @Test - void simpleScript() { - def baseDir = this.setupScripts(['simple.groovy']) - def builds = this.runner.runBuildScript('simple.groovy', baseDir.toURI().toURL()) - assertEquals(1, builds.size()) - assertEquals('test', builds[0].name) - } - - @Test - void testImport() { - def baseDir = this.setupScripts(['testImport.groovy', 'TestHtmlTask.groovy']) - def builds = this.runner.runBuildScript('testImport.groovy', baseDir.toURI().toURL()) - assertEquals(1, builds.size()) - assertEquals('test', builds[0].name) - } - - @Test - void buildSrcTest() { - def baseDir = File.createTempDir() - new FileTreeBuilder(baseDir).tap { - file('buildSrcTest.groovy').withWriter { - this.copyLocalResourceToWriter('buildSrcTest.groovy', it) - } - dir('buildSrc') { - file('AnotherTask.groovy').withWriter { - this.copyLocalResourceToWriter('buildSrc/AnotherTask.groovy', it) - } - } - } - def builds = this.runner.runBuildScript( - 'buildSrcTest.groovy', - baseDir.toURI().toURL(), - [new File(baseDir, 'buildSrc').toURI().toURL()] - ) - assertEquals(1, builds.size()) - assertEquals('test', builds[0].name) - } - - @Test - void withBinding(@Mock Consumer stringConsumer) { - def baseDir = this.setupScripts(['withBinding.groovy']) - this.runner.runBuildScript( - 'withBinding.groovy', - baseDir.toURI().toURL(), - [], - [stringConsumer: stringConsumer] - ) - verify(stringConsumer).accept('test') - } - - @Test - void customScript() { - def result = this.runner.runBuildScript { - build(name: 'test') { } - } - assertEquals(1, result.size()) - assertEquals('test', result[0].name) - } - - @Test - void oneBuildOutputDirWithFunction(@Mock Function mockOutputDirFunction) { - def r = this.runner.runBuildScript { - build(name: 'test') { - outputDirFunction = mockOutputDirFunction - } - } - assertEquals(1, r.size()) - def b0 = r[0] - assertEquals(mockOutputDirFunction, b0.outputDirFunction) - } - - @Test - void oneBuildOutputDirWithFile() { - def f = new File('test') - def r = this.runner.runBuildScript { - build(name: 'test') { - outputDir = f - } - } - assertEquals(1, r.size()) - def b0 = r[0] - assertEquals(f, b0.outputDirFunction.apply(b0) as File) - } - - @Test - void oneBuildOutputDirWithString() { - def r = this.runner.runBuildScript { - build(name: 'test') { - outputDir = 'test' - } - } - assertEquals(1, r.size()) - def b0 = r[0] - assertEquals('test', b0.outputDirFunction.apply(b0) as String) - } - - @Test - void oneBuildSiteSpec() { - def r = this.runner.runBuildScript { - build(name: 'test') { - siteSpec { - name = 'testSite' - baseUrl = 'https://testsite.com' - } - } - } - assertEquals(1, r.size()) - def b0 = r[0] - assertEquals(new SiteSpec('testSite', 'https://testsite.com'), b0.siteSpec) - } - - @Test - void oneBuildWithAbstractParent() { - def r = this.runner.runBuildScript { - abstractBuild(name: 'parent') { - siteSpec { - name = 'Test Site' - baseUrl = 'https://test.com' - } - } - - build(name: 'child', extending: 'parent') { - siteSpec { base -> - baseUrl = base.baseUrl + '/child' - } - } - } - - assertEquals(1, r.size()) - def b0 = r[0] - assertEquals(new SiteSpec('Test Site', 'https://test.com/child'), b0.siteSpec) - } - -}