Skip to content

Latest commit

 

History

History
225 lines (179 loc) · 6.03 KB

README.adoc

File metadata and controls

225 lines (179 loc) · 6.03 KB

CI License: LGPL v3

Gradle MaryTTS Component Plugin

Utility plugin to build MaryTTS components with Gradle.

Plugin behavior

To apply this plugin to a Gradle project, Gradle v6.0 or higher is recommended (although Gradle versions as low as v5.1 are compatible).

This plugin, when applied to a project, configures it as follows:

  1. The Java Library and Groovy plugins are applied

  2. Compatibility is set to Java 8

  3. The Maven Central repository is added, as well as DFKI’s MLT repository (to resolve the JTok dependency)

  4. Integration tests are set up via the integrationTest source set and task

  5. Testing is enabled using TestNG

Specifically for MaryTTS, additional classes and resources are generated and included in the main configuration classpath:

  1. A service loader

  2. A MaryTTS config file (see below)

  3. A MaryTTS component Config class

  4. Unit and integration tests (see below)

Plugin configuration

This plugin adds a marytts.component extension, which is configured like this:

marytts {
    component {
        name = 'Hello' // (1)
        packageName = 'my.world' // (2)
    }
}
  1. Custom component name

  2. Custom package name

This will generate the config file, service loader, and boilerplate Groovy and Java source code to test and use, respectively, this component with MaryTTS:

build
├── generatedIntegrationTestSrc
│   └── my # (1)
│       └── world
│           └── LoadHelloIT.groovy # (2)
├── generatedSrc
│   └── my # (1)
│       └── world
│           └── HelloConfig.java # (2)
└── generatedTestSrc
    └── my # (1)
        └── world
            └── HelloConfigTest.groovy # (2)
  1. Custom package path

  2. Class names derived from custom component name

YAML configuration

Since many MaryTTS components require detailed configuration, the configuration can be externalized into a YAML resource, like this:

marytts {
    component {
        config from: 'config.yaml' // (1)
    }
}
  1. YAML config source

If a YAML file is specified, it must be readable and valid, otherwise Gradle will fail to configure the project!
# A comment

locale: xy

foo:
    bar: foo baz # (1)

    qux: # (2)
    - quux
    - quuux

    fnord: 'jar:/path/to/the/fnord' # (3)
  1. Nested config keys will be flattened.

  2. A list will be converted to a config property with a trailing .list.

  3. A value with a jar: prefix (which should be quoted in YAML) will be treated as a classpath resource when the component runs in MaryTTS.

Generated config

The above YAML config will generate a configuration like this:

locale = xy
foo.bar = foo baz
foo.qux.list = \
    quux \
    quuux
foo.fnord = jar:/path/to/the/fnord

Generated test code

Groovy source code for unit and integration testing with TestNG will be generated to verify that the component can be loaded, and that all configured properties have the expected values. Any resources will be loaded as streams to ensure they exist on the classpath.

HelloConfigTest.groovy
package my.world

import marytts.config.*
import org.testng.annotations.*

class HelloConfigTest {

    HelloConfig config

    @BeforeMethod
    void setup() {
        config = new HelloConfig()
    }

    @Test
    public void isNotMainConfig() {
        assert config.isMainConfig() == false
    }

    @Test
    public void testConfigBaseClass() {
        assert config instanceof LanguageConfig
    }

    @Test
    public void canGetProperties() { // (1)
        assert config.properties.'locale' == 'xy'
        assert config.properties.'foo.bar' == 'foo baz'
        assert config.properties.'foo.qux.list'.tokenize().containsAll(['quux', 'quuux'])
        assert config.properties.'foo.fnord' == 'jar:/path/to/the/fnord'
    }
}
  1. Assertions generated from config

LoadHelloIT.groovy
package my.world

import marytts.server.MaryProperties
import marytts.util.MaryRuntimeUtils

import org.testng.annotations.*

class LoadHelloIT {

    @BeforeMethod
    void setup() {
        MaryRuntimeUtils.ensureMaryStarted()
    }

    @DataProvider
    Object[][] properties() {
        [ // (1)
            ['foo.bar', 'foo baz'],
            ['foo.qux.list', ['quux', 'quuux']],
            ['foo.fnord', 'jar:/path/to/the/fnord']
        ]
    }

    @Test(dataProvider = 'properties')
    public void canGetProperty(name, expected) {
        def actual
        switch (name) {
            case ~/.+\.list$/:
                actual = MaryProperties.getList(name)
                assert actual.containsAll(expected)
                break
            default:
                actual = MaryProperties.getProperty(name)
                assert expected == actual
                break
        }
        if ("$expected".startsWith('jar:')) {
            assert MaryProperties.getStream(name)
        }
    }
}
  1. Parameterized tests generated from config