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>
This commit is contained in:
Nik Everett 2021-03-24 16:57:50 -04:00 committed by GitHub
parent 2b9ed7d36f
commit 75342a2a71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 29 deletions

View file

@ -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(',')) { for (final String name : snippet.setup.split(',')) {
final String setup = setups[setupName] 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: ")

View file

@ -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]"
} }

View file

@ -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 is useful for creating and populating indexes used in the snippet. The `name`
code is defined in `docs/build.gradle`. See `// TESTSETUP` below for a is split on `,` and looked up in the `setups` defined in `docs/build.gradle`.
similar feature. 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

View file

@ -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:

View file

@ -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]]