Browse Source

Add `teardown` support for doc tests (#70831)

This adds named `teardown` support for doc tests similar to its support
for named `setup` section. This is useful when many doc files want to
share a similar `setup` AND `teardown`. I've introduced an example of
this in the CCR docs just to prove its works. We expect we'll use it for
datastreams as well.

Closes #70830

Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com>
Nik Everett 4 years ago
parent
commit
75342a2a71

+ 35 - 3
buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/RestTestsFromSnippetsTask.groovy

@@ -31,9 +31,20 @@ class RestTestsFromSnippetsTask extends SnippetsTask {
      */
      */
     private static final List BAD_LANGUAGES = ['json', 'javascript']
     private static final List BAD_LANGUAGES = ['json', 'javascript']
 
 
+    /**
+     * Test setups defined in the build instead of the docs so they can be
+     * shared between many doc files.
+     */
     @Input
     @Input
     Map<String, String> setups = new HashMap()
     Map<String, String> setups = new HashMap()
 
 
+    /**
+     * Test teardowns defined in the build instead of the docs so they can be
+     * shared between many doc files.
+     */
+    @Input
+    Map<String, String> teardowns = new HashMap()
+
     /**
     /**
      * A list of files that contain snippets that *probably* should be
      * A list of files that contain snippets that *probably* should be
      * converted to `// CONSOLE` but have yet to be converted. If a file is in
      * converted to `// CONSOLE` but have yet to be converted. If a file is in
@@ -281,19 +292,40 @@ class RestTestsFromSnippetsTask extends SnippetsTask {
             }
             }
 
 
             body(test, false)
             body(test, false)
+
+            if (test.teardown != null) {
+                teardown(test)
+            }
         }
         }
 
 
         private void setup(final Snippet snippet) {
         private void setup(final Snippet snippet) {
             // insert a setup defined outside of the docs
             // insert a setup defined outside of the docs
-            for (final String setupName : snippet.setup.split(',')) {
-                final String setup = setups[setupName]
+            for (final String name : snippet.setup.split(',')) {
+                final String setup = setups[name]
                 if (setup == null) {
                 if (setup == null) {
-                    throw new InvalidUserDataException("Couldn't find setup for $snippet")
+                    throw new InvalidUserDataException(
+                        "Couldn't find named setup $name for $snippet"
+                    )
                 }
                 }
+                current.println("# Named setup ${name}")
                 current.println(setup)
                 current.println(setup)
             }
             }
         }
         }
 
 
+        private void teardown(final Snippet snippet) {
+            // insert a teardown defined outside of the docs
+            for (final String name : snippet.teardown.split(',')) {
+                final String teardown = teardowns[name]
+                if (teardown == null) {
+                    throw new InvalidUserDataException(
+                        "Couldn't find named teardown $name for $snippet"
+                    )
+                }
+                current.println("# Named teardown ${name}")
+                current.println(teardown)
+            }
+        }
+
         private void response(Snippet response) {
         private void response(Snippet response) {
             if (null == response.skip) {
             if (null == response.skip) {
                 current.println("  - match: ")
                 current.println("  - match: ")

+ 11 - 2
buildSrc/src/main/groovy/org/elasticsearch/gradle/doc/SnippetsTask.groovy

@@ -32,10 +32,11 @@ class SnippetsTask extends DefaultTask {
     private static final String CATCH = /catch:\s*((?:\/[^\/]+\/)|[^ \]]+)/
     private static final String CATCH = /catch:\s*((?:\/[^\/]+\/)|[^ \]]+)/
     private static final String SKIP = /skip:([^\]]+)/
     private static final String SKIP = /skip:([^\]]+)/
     private static final String SETUP = /setup:([^ \]]+)/
     private static final String SETUP = /setup:([^ \]]+)/
+    private static final String TEARDOWN = /teardown:([^ \]]+)/
     private static final String WARNING = /warning:(.+)/
     private static final String WARNING = /warning:(.+)/
     private static final String NON_JSON = /(non_json)/
     private static final String NON_JSON = /(non_json)/
     private static final String TEST_SYNTAX =
     private static final String TEST_SYNTAX =
-        /(?:$CATCH|$SUBSTITUTION|$SKIP|(continued)|$SETUP|$WARNING|(skip_shard_failures)) ?/
+        /(?:$CATCH|$SUBSTITUTION|$SKIP|(continued)|$SETUP|$TEARDOWN|$WARNING|(skip_shard_failures)) ?/
 
 
     /**
     /**
      * Action to take on each snippet. Called with a single parameter, an
      * Action to take on each snippet. Called with a single parameter, an
@@ -226,10 +227,14 @@ class SnippetsTask extends DefaultTask {
                                 return
                                 return
                             }
                             }
                             if (it.group(7) != null) {
                             if (it.group(7) != null) {
-                                snippet.warnings.add(it.group(7))
+                                snippet.teardown = it.group(7)
                                 return
                                 return
                             }
                             }
                             if (it.group(8) != null) {
                             if (it.group(8) != null) {
+                                snippet.warnings.add(it.group(8))
+                                return
+                            }
+                            if (it.group(9) != null) {
                                 snippet.skipShardsFailures = true
                                 snippet.skipShardsFailures = true
                                 return
                                 return
                             }
                             }
@@ -341,6 +346,7 @@ class SnippetsTask extends DefaultTask {
         String language = null
         String language = null
         String catchPart = null
         String catchPart = null
         String setup = null
         String setup = null
+        String teardown = null
         boolean curl
         boolean curl
         List warnings = new ArrayList()
         List warnings = new ArrayList()
         boolean skipShardsFailures = false
         boolean skipShardsFailures = false
@@ -372,6 +378,9 @@ class SnippetsTask extends DefaultTask {
                 if (setup) {
                 if (setup) {
                     result += "[setup:$setup]"
                     result += "[setup:$setup]"
                 }
                 }
+                if (teardown) {
+                    result += "[teardown:$teardown]"
+                }
                 for (String warning in warnings) {
                 for (String warning in warnings) {
                     result += "[warning:$warning]"
                     result += "[warning:$warning]"
                 }
                 }

+ 7 - 3
docs/README.asciidoc

@@ -79,9 +79,13 @@ used for its modifiers:
   considered tests anyway but this is useful for explicitly documenting the
   considered tests anyway but this is useful for explicitly documenting the
   reason why the test shouldn't be run.
   reason why the test shouldn't be run.
   * `// TEST[setup:name]`: Run some setup code before running the snippet. This
   * `// TEST[setup:name]`: Run some setup code before running the snippet. This
-  is useful for creating and populating indexes used in the snippet. The setup
-  code is defined in `docs/build.gradle`. See `// TESTSETUP` below for a
-  similar feature.
+  is useful for creating and populating indexes used in the snippet. The `name`
+  is split on `,` and looked up in the `setups` defined in `docs/build.gradle`.
+  See `// TESTSETUP` below for a similar feature.
+  * `// TEST[teardown:name]`: Run some teardown code after the snippet.
+  This is useful for performing hidden cleanup, such as deleting index templates. The
+  `name` is split on `,` and looked up in the `teardowns` defined in
+  `docs/build.gradle`. See `// TESTSETUP` below for a similar feature.
   * `// TEST[warning:some warning]`: Expect the response to include a `Warning`
   * `// TEST[warning:some warning]`: Expect the response to include a `Warning`
   header. If the response doesn't include a `Warning` header with the exact
   header. If the response doesn't include a `Warning` header with the exact
   text then the test fails. If the response includes `Warning` headers that
   text then the test fails. If the response includes `Warning` headers that

+ 24 - 0
docs/build.gradle

@@ -1295,6 +1295,30 @@ setups['remote_cluster_and_leader_index'] = setups['remote_cluster'] + '''
             index.soft_deletes.enabled: true
             index.soft_deletes.enabled: true
 '''
 '''
 
 
+setups['remote_cluster_and_leader_index_and_follower_index'] = setups['remote_cluster_and_leader_index'] + '''
+  - do:
+      raw:
+        method: PUT
+        path: 'follower_index/_ccr/follow'
+        wait_for_active_shards: 1
+        body: |
+          {
+            "remote_cluster" : "remote_cluster",
+            "leader_index" : "leader_index"
+          }
+  - is_true: follow_index_created
+  - is_true: follow_index_shards_acked
+  - is_true: index_following_started
+'''
+
+teardowns['pause_follow'] = '''
+  - do:
+      raw:
+        method: POST
+        path: 'follower_index/_ccr/pause_follow'
+  - is_true: acknowledged
+'''
+
 setups['seats'] = '''
 setups['seats'] = '''
   - do:
   - do:
         indices.create:
         indices.create:

+ 1 - 21
docs/reference/ccr/managing.asciidoc

@@ -1,27 +1,6 @@
 [role="xpack"]
 [role="xpack"]
 [testenv="platinum"]
 [testenv="platinum"]
 
 
-//////////////////////////
-
-[source,console]
---------------------------------------------------
-PUT /follower_index/_ccr/follow?wait_for_active_shards=1
-{
-  "remote_cluster" : "remote_cluster",
-  "leader_index" : "leader_index"
-}
---------------------------------------------------
-// TESTSETUP
-// TEST[setup:remote_cluster_and_leader_index]
-
-[source,console]
---------------------------------------------------
-POST /follower_index/_ccr/pause_follow
---------------------------------------------------
-// TEARDOWN
-
-//////////////////////////
-
 [[ccr-managing]]
 [[ccr-managing]]
 === Manage {ccr}
 === Manage {ccr}
 Use the following information to manage {ccr} tasks, such as inspecting
 Use the following information to manage {ccr} tasks, such as inspecting
@@ -135,6 +114,7 @@ PUT /follower_index/_ccr/follow?wait_for_active_shards=1
   "leader_index" : "leader_index"
   "leader_index" : "leader_index"
 }
 }
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
+// TEST[setup:remote_cluster_and_leader_index_and_follower_index teardown:pause_follow]
 ====
 ====
 
 
 [[ccr-terminate-replication]]
 [[ccr-terminate-replication]]