You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/05/03 08:13:38 UTC

[groovy] branch GROOVY-9804 updated (f43e353 -> d526aa9)

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a change to branch GROOVY-9804
in repository https://gitbox.apache.org/repos/asf/groovy.git.


 discard f43e353  GROOVY-9804: Support TOML
     new d526aa9  GROOVY-9804: Support TOML

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (f43e353)
            \
             N -- N -- N   refs/heads/GROOVY-9804 (d526aa9)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 subprojects/groovy-toml/src/main/java/groovy/toml/TomlBuilder.java      | 2 +-
 .../groovy-toml/src/main/java/groovy/toml/TomlRuntimeException.java     | 2 +-
 subprojects/groovy-toml/src/main/java/groovy/toml/TomlSlurper.java      | 2 +-
 .../src/main/java/org/apache/groovy/toml/util/TomlConverter.java        | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

[groovy] 01/01: GROOVY-9804: Support TOML

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY-9804
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit d526aa9809300d42cf8ae0a218b9a9e43020fb85
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon May 3 16:08:49 2021 +0800

    GROOVY-9804: Support TOML
---
 settings.gradle                                    |   1 +
 subprojects/groovy-binary/src/spec/doc/index.adoc  |   2 +
 subprojects/groovy-toml/build.gradle               |  40 ++++++
 .../src/main/java/groovy/toml/TomlBuilder.java     | 145 +++++++++++++++++++++
 .../java/groovy/toml/TomlRuntimeException.java     |  40 ++++++
 .../src/main/java/groovy/toml/TomlSlurper.java     |  94 +++++++++++++
 .../org/apache/groovy/toml/util/TomlConverter.java |  74 +++++++++++
 .../groovy-toml/src/spec/doc/toml-userguide.adoc   | 101 ++++++++++++++
 .../spec/test/groovy/toml/TomlBuilderTest.groovy   |  55 ++++++++
 .../spec/test/groovy/toml/TomlParserTest.groovy    | 110 ++++++++++++++++
 .../groovy/toml/TomlJavadocAssertionTest.groovy    |  28 ++++
 11 files changed, 690 insertions(+)

diff --git a/settings.gradle b/settings.gradle
index 0c7e7f4..d83b6fb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -58,6 +58,7 @@ def subprojects = [
         'groovy-test',
         'groovy-test-junit5',
         'groovy-testng',
+        'groovy-toml',
         'groovy-typecheckers',
         'groovy-xml',
         'groovy-yaml',
diff --git a/subprojects/groovy-binary/src/spec/doc/index.adoc b/subprojects/groovy-binary/src/spec/doc/index.adoc
index 00b756e..52f199f 100644
--- a/subprojects/groovy-binary/src/spec/doc/index.adoc
+++ b/subprojects/groovy-binary/src/spec/doc/index.adoc
@@ -106,6 +106,8 @@ include::../../../../../subprojects/groovy-xml/src/spec/doc/xml-userguide.adoc[l
 
 include::../../../../../subprojects/groovy-yaml/src/spec/doc/yaml-userguide.adoc[leveloffset=+2]
 
+include::../../../../../subprojects/groovy-toml/src/spec/doc/toml-userguide.adoc[leveloffset=+2]
+
 include::../../../../../subprojects/groovy-contracts/src/spec/doc/contracts-userguide.adoc[leveloffset=+2]
 
 === Scripting Ant tasks
diff --git a/subprojects/groovy-toml/build.gradle b/subprojects/groovy-toml/build.gradle
new file mode 100644
index 0000000..8b5b626
--- /dev/null
+++ b/subprojects/groovy-toml/build.gradle
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+plugins {
+    id 'org.apache.groovy-library'
+}
+
+dependencies {
+    api rootProject  // TomlBuilder extends GroovyObjectSupport...
+    implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-toml:${versions.jackson}"
+    implementation project(':groovy-json')
+    testImplementation project(':groovy-test')
+    testRuntimeOnly project(':groovy-ant') // for JavadocAssertionTests
+}
+
+plugins.withId('eclipse') {
+    eclipse.classpath.file.whenMerged {
+        entries.removeAll { entry -> entry.path in ['/groovy-ant', '/groovy-groovydoc'] }
+    }
+}
+
+groovyLibrary {
+    optionalModule()
+    withoutBinaryCompatibilityChecks()
+}
diff --git a/subprojects/groovy-toml/src/main/java/groovy/toml/TomlBuilder.java b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlBuilder.java
new file mode 100644
index 0000000..7a04571
--- /dev/null
+++ b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlBuilder.java
@@ -0,0 +1,145 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml;
+
+import groovy.json.JsonBuilder;
+import groovy.lang.Closure;
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.Writable;
+import org.apache.groovy.toml.util.TomlConverter;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *  A builder for creating TOML payloads.
+ *
+ *  @since 4.0.0
+ */
+public class TomlBuilder extends GroovyObjectSupport implements Writable {
+    private JsonBuilder jsonBuilder;
+
+    public TomlBuilder() {
+        this.jsonBuilder = new JsonBuilder();
+    }
+
+    public Object getContent() {
+        return jsonBuilder.getContent();
+    }
+
+    /**
+     * Named arguments can be passed to the TOML builder instance to create a root TOML object
+     *
+     * @param m a map of key / value pairs
+     * @return a map of key / value pairs
+     */
+    public Object call(Map m) {
+        return jsonBuilder.call(m);
+    }
+
+    /**
+     * A list of elements as arguments to the TOML builder creates a root TOML array
+     *
+     * @param l a list of values
+     * @return a list of values
+     */
+    public Object call(List l) {
+        return jsonBuilder.call(l);
+    }
+
+    /**
+     * Varargs elements as arguments to the TOML builder create a root TOML array
+     *
+     * @param args an array of values
+     * @return a list of values
+     */
+    public Object call(Object... args) {
+        return jsonBuilder.call(args);
+    }
+
+    /**
+     * A collection and closure passed to a TOML builder will create a root TOML array applying
+     * the closure to each object in the collection
+
+     * @param coll a collection
+     * @param c a closure used to convert the objects of coll
+     * @return a list of values
+     */
+    public Object call(Iterable coll, Closure c) {
+        return jsonBuilder.call(coll, c);
+    }
+
+    /**
+     * Delegates to {@link #call(Iterable, Closure)}
+     * @param coll
+     * @param c
+     */
+    public Object call(Collection coll, Closure c) {
+        return jsonBuilder.call(coll, c);
+    }
+
+    /**
+     * A closure passed to a TOML builder will create a root TOML object
+     *
+     * @param c a closure whose method call statements represent key / values of a TOML object
+     * @return a map of key / value pairs
+     */
+    public Object call(Closure c) {
+        return jsonBuilder.call(c);
+    }
+
+    /**
+     * A method call on the TOML builder instance will create a root object with only one key
+     * whose name is the name of the method being called.
+     *
+     * @param name the single key
+     * @param args the value associated with the key
+     * @return a map with a single key
+     */
+    @Override
+    public Object invokeMethod(String name, Object args) {
+        return jsonBuilder.invokeMethod(name, args);
+    }
+
+    /**
+     * Serializes the internal data structure built with the builder to a conformant TOML payload string
+     *
+     * @return a TOML output
+     */
+    @Override
+    public String toString() {
+        return TomlConverter.convertJsonToToml(new StringReader(jsonBuilder.toString()));
+    }
+
+    /**
+     * The TOML builder implements the <code>Writable</code> interface,
+     * so that you can have the builder serialize itself the TOML payload to a writer.
+     *
+     * @param out a writer on which to serialize the TOML payload
+     * @return the writer
+     */
+    @Override
+    public Writer writeTo(Writer out) throws IOException {
+        return out.append(toString());
+    }
+}
diff --git a/subprojects/groovy-toml/src/main/java/groovy/toml/TomlRuntimeException.java b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlRuntimeException.java
new file mode 100644
index 0000000..e2ad047
--- /dev/null
+++ b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlRuntimeException.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml;
+
+import groovy.lang.GroovyRuntimeException;
+
+/**
+ * Represents runtime exception occurred when parsing or building TOML
+ *
+ * @since 4.0.0
+ */
+public class TomlRuntimeException extends GroovyRuntimeException {
+    public TomlRuntimeException(String msg) {
+        super(msg);
+    }
+
+    public TomlRuntimeException(Throwable cause) {
+        super(cause);
+    }
+
+    public TomlRuntimeException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}
diff --git a/subprojects/groovy-toml/src/main/java/groovy/toml/TomlSlurper.java b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlSlurper.java
new file mode 100644
index 0000000..5b312ad
--- /dev/null
+++ b/subprojects/groovy-toml/src/main/java/groovy/toml/TomlSlurper.java
@@ -0,0 +1,94 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml;
+
+import groovy.json.JsonSlurper;
+import org.apache.groovy.toml.util.TomlConverter;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ *  Represents a TOML parser
+ *
+ *  @since 4.0.0
+ */
+public class TomlSlurper {
+    private JsonSlurper jsonSlurper;
+
+    public TomlSlurper() {
+        this.jsonSlurper = new JsonSlurper();
+    }
+
+    /**
+     * Parse the content of the specified toml into a tree of Nodes.
+     *
+     * @param toml the content of toml
+     * @return the root node of the parsed tree of Nodes
+     */
+    public Object parseText(String toml) {
+        return this.parse(new StringReader(toml));
+    }
+
+    /**
+     * Parse the content of the specified reader into a tree of Nodes.
+     *
+     * @param reader the reader of toml
+     * @return the root node of the parsed tree of Nodes
+     */
+    public Object parse(Reader reader) {
+        return jsonSlurper.parse(new StringReader(TomlConverter.convertTomlToJson(reader)));
+    }
+
+    /**
+     * Parse the content of the specified reader into a tree of Nodes.
+     *
+     * @param stream the reader of toml
+     * @return the root node of the parsed tree of Nodes
+     */
+    public Object parse(InputStream stream) {
+        return parse(new InputStreamReader(stream));
+    }
+
+    /**
+     * Parse the content of the specified file into a tree of Nodes.
+     *
+     * @param file the reader of toml
+     * @return the root node of the parsed tree of Nodes
+     */
+    public Object parse(java.io.File file) throws IOException {
+        return parse(file.toPath());
+    }
+
+    /**
+     * Parse the content of the specified path into a tree of Nodes.
+     *
+     * @param path the reader of toml
+     * @return the root node of the parsed tree of Nodes
+     */
+    public Object parse(Path path) throws IOException {
+        // note: convert to an input stream to allow the support of foreign file objects
+        return parse(Files.newInputStream(path));
+    }
+}
diff --git a/subprojects/groovy-toml/src/main/java/org/apache/groovy/toml/util/TomlConverter.java b/subprojects/groovy-toml/src/main/java/org/apache/groovy/toml/util/TomlConverter.java
new file mode 100644
index 0000000..4e22288
--- /dev/null
+++ b/subprojects/groovy-toml/src/main/java/org/apache/groovy/toml/util/TomlConverter.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.groovy.toml.util;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.toml.TomlFactory;
+import com.fasterxml.jackson.dataformat.toml.TomlMapper;
+import groovy.toml.TomlRuntimeException;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+/**
+ *  A converter for converting TOML to JSON, vice versa
+ *  @since 4.0.0
+ */
+public class TomlConverter {
+    /**
+     * Convert toml to json
+     * @param tomlReader the reader of toml
+     * @return the text of json
+     */
+    public static String convertTomlToJson(Reader tomlReader) {
+        try (Reader reader = tomlReader) {
+            Object yaml = new ObjectMapper(new TomlFactory()).readValue(reader, Object.class);
+
+            return new ObjectMapper().writeValueAsString(yaml);
+        } catch (IOException e) {
+            throw new TomlRuntimeException(e);
+        }
+    }
+
+    /**
+     * Convert json to toml
+     * @param jsonReader the reader of json
+     * @return the text of toml
+     */
+    public static String convertJsonToToml(Reader jsonReader) {
+        try (Reader reader = jsonReader) {
+            JsonNode json = new ObjectMapper().readTree(reader);
+
+            return new TomlMapper().writeValueAsString(json);
+        } catch (IOException e) {
+            throw new TomlRuntimeException(e);
+        }
+    }
+
+    private TomlConverter() {}
+
+    public static void main(String[] args) {
+        String json = TomlConverter.convertTomlToJson(new StringReader("number = 42"));
+        System.out.println(json);
+        String toml = TomlConverter.convertJsonToToml(new StringReader(json));
+        System.out.println(toml);
+    }
+}
diff --git a/subprojects/groovy-toml/src/spec/doc/toml-userguide.adoc b/subprojects/groovy-toml/src/spec/doc/toml-userguide.adoc
new file mode 100644
index 0000000..d59ab19
--- /dev/null
+++ b/subprojects/groovy-toml/src/spec/doc/toml-userguide.adoc
@@ -0,0 +1,101 @@
+//////////////////////////////////////////
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+//////////////////////////////////////////
+ifndef::core-semantics[]
+:core-semantics: core-semantics.adoc
+endif::[]
+
+= Processing TOML
+
+Groovy has an optional `groovy-toml` module which provides support for converting between Groovy objects and TOML. The classes dedicated to
+TOML serialisation and parsing are found in the `groovy.toml` package.
+
+[[toml_tomlslurper]]
+== TomlSlurper
+
+`TomlSlurper` is a class that parses TOML text or reader content into Groovy data structures (objects) such as maps, lists and
+primitive types like `Integer`, `Double`, `Boolean` and `String`.
+
+The class comes with a bunch of overloaded `parse` methods plus some special methods such as `parseText`
+and others. For the next example we will use the `parseText` method. It parses a TOML `String` and recursively converts it to a
+list or map of objects. The other `parse*` methods are similar in that they return a TOML `String` but for different parameter
+types.
+
+[source,groovy]
+----
+include::../test/groovy/toml/TomlParserTest.groovy[tags=parse_text,indent=0]
+----
+
+Notice the result is a plain map and can be handled like a normal Groovy object instance. `TomlSlurper` parses the
+given TOML as defined by the https://toml.io/en/v1.0.0-rc.3[Tom's Obvious, Minimal Language].
+
+
+As `TomlSlurper` is returning pure Groovy object instances without any special TOML classes in the back, its usage
+is transparent. In fact, `TomlSlurper` results conform to GPath expressions. GPath is a powerful expression language
+that is supported by multiple slurpers for different data formats (`XmlSlurper` for XML being one example).
+
+[NOTE]
+For more details please have a look at the section on <<{core-semantics}#gpath_expressions,GPath expressions>>.
+
+The following table gives an overview of the TOML types and the corresponding Groovy data types:
+
+[cols="1,3" options="header"]
+|===
+|TOML
+|Groovy
+
+|string
+|`java.lang.String`
+
+|number
+|`java.lang.BigDecimal` or `java.lang.Integer`
+
+|object
+|`java.util.LinkedHashMap`
+
+|array
+|`java.util.ArrayList`
+
+|true
+|`true`
+
+|false
+|`false`
+
+|null
+|`null`
+
+|date
+|`java.util.Date` based on the `yyyy-MM-dd'T'HH:mm:ssZ` date format
+|===
+
+[NOTE]
+Whenever a value in TOML is `null`, `TomlSlurper` supplements it with the Groovy `null` value. This is in contrast to other
+TOML parsers that represent a `null` value with a library-provided singleton object.
+
+=== Builders
+
+Another way to create TOML from Groovy is to use `TomlBuilder`. The builder provide a
+DSL which allows to formulate an object graph which is then converted to TOML.
+
+[source,groovy]
+----
+include::../test/groovy/toml/TomlBuilderTest.groovy[tags=build_text,indent=0]
+----
diff --git a/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlBuilderTest.groovy b/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlBuilderTest.groovy
new file mode 100644
index 0000000..36e5b4a
--- /dev/null
+++ b/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlBuilderTest.groovy
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml
+
+import groovy.test.GroovyTestCase
+
+class TomlBuilderTest extends GroovyTestCase {
+
+    void testBuild() {
+        // tag::build_text[]
+        def builder = new TomlBuilder()
+        builder.records {
+            car {
+                name 'HSV Maloo'
+                make 'Holden'
+                year 2006
+                country 'Australia'
+                homepage new URL('http://example.org')
+                record {
+                    type 'speed'
+                    description 'production pickup truck with speed of 271kph'
+                }
+            }
+        }
+
+        println builder.toString()
+
+        assert builder.toString() == '''\
+records.car.name = 'HSV Maloo'
+records.car.make = 'Holden'
+records.car.year = 2006
+records.car.country = 'Australia'
+records.car.homepage = 'http://example.org'
+records.car.record.type = 'speed'
+records.car.record.description = 'production pickup truck with speed of 271kph'
+'''
+        // end::build_text[]
+    }
+}
\ No newline at end of file
diff --git a/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlParserTest.groovy b/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlParserTest.groovy
new file mode 100644
index 0000000..dacef27
--- /dev/null
+++ b/subprojects/groovy-toml/src/spec/test/groovy/toml/TomlParserTest.groovy
@@ -0,0 +1,110 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml
+
+
+import groovy.test.GroovyTestCase
+
+class TomlParserTest extends GroovyTestCase {
+
+    void testParse() {
+        // tag::parse_text[]
+        def ts = new TomlSlurper()
+        def toml = ts.parseText '''
+language = "groovy"
+sudo = "required"
+dist = "trusty"
+before_script = [ "unset _JAVA_OPTIONS\\n\\n    \\n" ]
+
+[[matrix.include]]
+jdk = "openjdk10"
+
+[[matrix.include]]
+jdk = "oraclejdk9"
+
+[[matrix.include]]
+jdk = "oraclejdk8"
+'''
+
+        assert 'groovy' == toml.language
+        assert 'required' == toml.sudo
+        assert 'trusty' == toml.dist
+        assert ['openjdk10', 'oraclejdk9', 'oraclejdk8'] ==  toml.matrix.include.jdk
+        assert ['unset _JAVA_OPTIONS'] == toml.before_script*.trim()
+        // end::parse_text[]
+    }
+
+    void testBuildAndParse() {
+        def builder = new TomlBuilder()
+        builder.records {
+            car {
+                name 'HSV Maloo'
+                make 'Holden'
+                year 2006
+                country 'Australia'
+                homepage new URL('http://example.org')
+                record {
+                    type 'speed'
+                    description 'production pickup truck with speed of 271kph'
+                }
+            }
+        }
+
+        def ts = new TomlSlurper()
+        def toml = ts.parseText(builder.toString())
+
+        assert 'HSV Maloo' == toml.records.car.name
+        assert 'Holden' == toml.records.car.make
+        assert 2006 == toml.records.car.year
+        assert 'Australia' == toml.records.car.country
+        assert 'http://example.org' == toml.records.car.homepage
+        assert 'speed' == toml.records.car.record.type
+        assert 'production pickup truck with speed of 271kph' == toml.records.car.record.description
+    }
+
+
+    void testParsePath() {
+        def file = File.createTempFile('test','yml')
+        file.deleteOnExit()
+        file.text = '''
+language = "groovy"
+sudo = "required"
+dist = "trusty"
+
+[[matrix.include]]
+jdk = "openjdk10"
+
+[[matrix.include]]
+jdk = "oraclejdk9"
+
+[[matrix.include]]
+jdk = "oraclejdk8"
+'''
+
+        def ts = new TomlSlurper()
+        def toml = ts.parse(file.toPath())
+
+        // check
+        assert 'groovy' == toml.language
+        assert 'required' == toml.sudo
+        assert 'trusty' == toml.dist
+        assert ['openjdk10', 'oraclejdk9', 'oraclejdk8'] ==  toml.matrix.include.jdk
+
+    }
+}
diff --git a/subprojects/groovy-toml/src/test/groovy/groovy/toml/TomlJavadocAssertionTest.groovy b/subprojects/groovy-toml/src/test/groovy/groovy/toml/TomlJavadocAssertionTest.groovy
new file mode 100644
index 0000000..43c6e4f
--- /dev/null
+++ b/subprojects/groovy-toml/src/test/groovy/groovy/toml/TomlJavadocAssertionTest.groovy
@@ -0,0 +1,28 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.toml
+
+import groovy.test.JavadocAssertionTestSuite
+import org.junit.runner.RunWith
+import org.junit.runners.Suite
+
+@RunWith(Suite)
+@Suite.SuiteClasses(JavadocAssertionTestSuite)
+class TomlJavadocAssertionTest {
+}