summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/echo/echo.yaml24
-rw-r--r--examples/muck/muck.yaml52
-rw-r--r--examples/website/website.yaml17
-rw-r--r--share/python/lib/daemon.yaml77
-rw-r--r--share/python/lib/files.yaml100
-rw-r--r--share/python/lib/runcmd.yaml96
-rw-r--r--share/python/lib/runcmd_test.yaml8
-rw-r--r--share/rust/lib/datadir.yaml8
-rw-r--r--share/rust/lib/files.yaml100
-rw-r--r--share/rust/lib/runcmd.yaml88
-rw-r--r--src/bindings.rs62
-rw-r--r--subplot.md110
-rw-r--r--subplot.yaml63
-rw-r--r--subplotlib/subplotlib.yaml26
14 files changed, 619 insertions, 212 deletions
diff --git a/examples/echo/echo.yaml b/examples/echo/echo.yaml
index 7be6e96..bcbdf87 100644
--- a/examples/echo/echo.yaml
+++ b/examples/echo/echo.yaml
@@ -1,20 +1,32 @@
- when: user runs echo without arguments
- function: run_echo_without_args
+ impl:
+ bash:
+ function: run_echo_without_args
- when: user runs echo with arguments (?P<args>.+)
- function: run_echo_with_args
+ impl:
+ bash:
+ function: run_echo_with_args
regex: true
- then: exit code is (?P<exit_code>\d+)
- function: exit_code_is
+ impl:
+ bash:
+ function: exit_code_is
regex: true
- then: standard output contains a newline
- function: stdout_is_a_newline
+ impl:
+ bash:
+ function: stdout_is_a_newline
- then: standard output contains "(?P<text>.*)"
- function: stdout_is_text
+ impl:
+ bash:
+ function: stdout_is_text
regex: true
- then: standard error is empty
- function: stderr_is_empty
+ impl:
+ bash:
+ function: stderr_is_empty
diff --git a/examples/muck/muck.yaml b/examples/muck/muck.yaml
index 21fe303..10f67ee 100644
--- a/examples/muck/muck.yaml
+++ b/examples/muck/muck.yaml
@@ -1,47 +1,73 @@
- given: "a fresh Muck server"
- function: fixme
+ impl:
+ python:
+ function: fixme
- given: "I am {name}"
- function: fixme
+ impl:
+ python:
+ function: fixme
- given: "I am {name}, with super capability"
- function: fixme
+ impl:
+ python:
+ function: fixme
- when: "I do POST /res with (?P<json>\\{.*\\})"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- when: "I do PUT /res with Muck-Id: \\{(?P<id>\\S+)\\}, Muck-Revision: \\{(?P<rev>\\S+)\\}, and body (?P<json>\\{.*\\})"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- when: "I do GET /res with Muck-Id: \\{(?P<id>\\S+)\\}"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- when: "I do DELETE /res with Muck-Id: \\{(?P<id>\\S+)\\}"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- when: "I restart Muck"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- then: "response code is (?P<code>\\d+)"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- then: "header {header} is {name}"
- function: fixme
+ impl:
+ python:
+ function: fixme
- then: "header (?P<header>\\S+) matches \\{(?P<name>\\S+)\\}"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- then: "body matches (?P<json>\\{.*\\})"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
- then: "revisions \\{(?P<rev1>\\S+)\\} and \\{(?P<rev2>\\S+)\\} are different"
- function: fixme
+ impl:
+ python:
+ function: fixme
regex: true
diff --git a/examples/website/website.yaml b/examples/website/website.yaml
index 401b16e..a3afc1b 100644
--- a/examples/website/website.yaml
+++ b/examples/website/website.yaml
@@ -1,12 +1,19 @@
- given: website {url}
- function: remember_url
+ impl:
+ python:
+ function: remember_url
- when: I look at the front page
- function: fetch_url
+ impl:
+ python:
+ function: fetch_url
- then: it mentions "{text:text}"
- function: page_contains
+ impl:
+ python:
+ function: page_contains
- then: it doesn't contain "{text:text}"
- function: page_doesnt_contain
-
+ impl:
+ python:
+ function: page_doesnt_contain
diff --git a/share/python/lib/daemon.yaml b/share/python/lib/daemon.yaml
index f4a2f86..5cbc7d0 100644
--- a/share/python/lib/daemon.yaml
+++ b/share/python/lib/daemon.yaml
@@ -1,59 +1,94 @@
- given: there is no "{args:text}" process
- function: daemon_no_such_process
+ impl:
+ python:
+ function: daemon_no_such_process
- given: a daemon helper shell script {filename}
- function: _daemon_shell_script
+ impl:
+ python:
+ function: _daemon_shell_script
- when: I start "{path}{args:text}" as a background process as {name}, on port {port}
- function: daemon_start_on_port
+ impl:
+ python:
+ function: daemon_start_on_port
- when: I start "(?P<path>[^ "]+)(?P<args>[^"]*)" as a background process as (?P<name>[^,]+), on port (?P<port>\d+), with environment (?P<env>.*)
regex: true
- function: daemon_start_on_port
+ impl:
+ python:
+ function: daemon_start_on_port
- when: I try to start "{path}{args:text}" as {name}, on port {port}
- function: _daemon_start_soonish
- cleanup: _daemon_stop_soonish
+ impl:
+ python:
+ function: _daemon_start_soonish
+ cleanup: _daemon_stop_soonish
- when: I try to start "(?P<path>[^ "]+)(?P<args>[^"]*)" as (?P<name>[^,]+), on port (?P<port>\d+), with environment (?P<env>.*)
regex: true
- function: _daemon_start_soonish
- cleanup: _daemon_stop_soonish
+ impl:
+ python:
+ function: _daemon_start_soonish
+ cleanup: _daemon_stop_soonish
- when: I start "{path}{args:text}" as a background process as {name}
- function: _daemon_start
+ impl:
+ python:
+ function: _daemon_start
- when: I start "(?P<path>[^ "]+)(?P<args>[^"]*)" as a background process as (?P<name>[^,]+), with environment (?P<env>.*)
regex: true
- function: _daemon_start
+ impl:
+ python:
+ function: _daemon_start
- when: I stop background process {name}
- function: daemon_stop
+ impl:
+ python:
+ function: daemon_stop
- when: daemon {name} has produced output
- function: daemon_has_produced_output
+ impl:
+ python:
+ function: daemon_has_produced_output
- then: a process "{args:text}" is running
- function: daemon_process_exists
+ impl:
+ python:
+ function: daemon_process_exists
- then: there is no "{args:text}" process
- function: daemon_no_such_process
+ impl:
+ python:
+ function: daemon_no_such_process
- then: starting daemon fails with "{message:text}"
- function: daemon_start_fails_with
+ impl:
+ python:
+ function: daemon_start_fails_with
- then: starting the daemon succeeds
- function: daemon_start_succeeds
+ impl:
+ python:
+ function: daemon_start_succeeds
- then: daemon {name} stdout is "{text:text}"
- function: daemon_stdout_is
+ impl:
+ python:
+ function: daemon_stdout_is
- then: daemon {name} stdout contains "{text:text}"
- function: daemon_stdout_contains
+ impl:
+ python:
+ function: daemon_stdout_contains
- then: daemon {name} stdout doesn't contain "{text:text}"
- function: daemon_stdout_doesnt_contain
+ impl:
+ python:
+ function: daemon_stdout_doesnt_contain
- then: daemon {name} stderr is "{text:text}"
- function: daemon_stderr_is
-
+ impl:
+ python:
+ function: daemon_stderr_is
diff --git a/share/python/lib/files.yaml b/share/python/lib/files.yaml
index f18b8cd..64a2d14 100644
--- a/share/python/lib/files.yaml
+++ b/share/python/lib/files.yaml
@@ -1,83 +1,133 @@
- given: file {filename}
- function: files_create_from_embedded
+ impl:
+ python:
+ function: files_create_from_embedded
types:
filename: file
- given: file {filename_on_disk} from {embedded_filename}
- function: files_create_from_embedded_with_other_name
+ impl:
+ python:
+ function: files_create_from_embedded_with_other_name
types:
embedded_filename: file
- given: file {filename} has modification time {year}-{month}-{day} {hour}:{minute}:{second}
- function: files_touch_with_timestamp
+ impl:
+ python:
+ function: files_touch_with_timestamp
- when: I write "(?P<text>.*)" to file (?P<filename>\S+)
regex: true
- function: files_create_from_text
+ impl:
+ python:
+ function: files_create_from_text
- when: I remember metadata for file {filename}
- function: files_remember_metadata
+ impl:
+ python:
+ function: files_remember_metadata
- when: I touch file {filename}
- function: files_touch
+ impl:
+ python:
+ function: files_touch
- then: file {filename} exists
- function: files_file_exists
+ impl:
+ python:
+ function: files_file_exists
- then: file {filename} does not exist
- function: files_file_does_not_exist
+ impl:
+ python:
+ function: files_file_does_not_exist
- then: only files (?P<filenames>.+) exist
- function: files_only_these_exist
+ impl:
+ python:
+ function: files_only_these_exist
regex: true
- then: file (?P<filename>\S+) contains "(?P<data>.*)"
regex: true
- function: files_file_contains
+ impl:
+ python:
+ function: files_file_contains
- then: file (?P<filename>\S+) matches regex /(?P<regex>.*)/
regex: true
- function: files_file_matches_regex
+ impl:
+ python:
+ function: files_file_matches_regex
- then: file (?P<filename>\S+) matches regex "(?P<regex>.*)"
regex: true
- function: files_file_matches_regex
+ impl:
+ python:
+ function: files_file_matches_regex
- then: files {filename1} and {filename2} match
- function: files_match
+ impl:
+ python:
+ function: files_match
- then: file {filename} has same metadata as before
- function: files_has_remembered_metadata
+ impl:
+ python:
+ function: files_has_remembered_metadata
- then: file {filename} has different metadata from before
- function: files_has_different_metadata
+ impl:
+ python:
+ function: files_has_different_metadata
- then: file {filename} has changed from before
- function: files_has_different_metadata
+ impl:
+ python:
+ function: files_has_different_metadata
- then: file {filename} has a very recent modification time
- function: files_mtime_is_recent
+ impl:
+ python:
+ function: files_mtime_is_recent
- then: file {filename} has a very old modification time
- function: files_mtime_is_ancient
+ impl:
+ python:
+ function: files_mtime_is_ancient
- given: a directory {path}
- function: files_make_directory
+ impl:
+ python:
+ function: files_make_directory
- when: I create directory {path}
- function: files_make_directory
+ impl:
+ python:
+ function: files_make_directory
- when: I remove directory {path}
- function: files_remove_directory
+ impl:
+ python:
+ function: files_remove_directory
- then: directory {path} exists
- function: files_directory_exists
+ impl:
+ python:
+ function: files_directory_exists
- then: directory {path} does not exist
- function: files_directory_does_not_exist
+ impl:
+ python:
+ function: files_directory_does_not_exist
- then: directory {path} is empty
- function: files_directory_is_empty
+ impl:
+ python:
+ function: files_directory_is_empty
- then: directory {path} is not empty
- function: files_directory_is_not_empty
+ impl:
+ python:
+ function: files_directory_is_not_empty
diff --git a/share/python/lib/runcmd.yaml b/share/python/lib/runcmd.yaml
index a5119d8..a01cfac 100644
--- a/share/python/lib/runcmd.yaml
+++ b/share/python/lib/runcmd.yaml
@@ -1,91 +1,135 @@
# Steps to run commands.
- given: helper script {filename} for runcmd
- function: runcmd_helper_script
+ impl:
+ python:
+ function: runcmd_helper_script
- given: srcdir is in the PATH
- function: runcmd_helper_srcdir_path
+ impl:
+ python:
+ function: runcmd_helper_srcdir_path
- when: I run (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: runcmd_step
+ impl:
+ python:
+ function: runcmd_step
- when: I run, in (?P<dirname>\S+), (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: runcmd_step_in
+ impl:
+ python:
+ function: runcmd_step_in
- when: I try to run (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: runcmd_try_to_run
+ impl:
+ python:
+ function: runcmd_try_to_run
- when: I try to run, in (?P<dirname>\S+), (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: runcmd_try_to_run_in
+ impl:
+ python:
+ function: runcmd_try_to_run_in
# Steps to examine exit code of latest command.
- then: exit code is {exit}
- function: runcmd_exit_code_is
+ impl:
+ python:
+ function: runcmd_exit_code_is
- then: exit code is not {exit}
- function: runcmd_exit_code_is_not
+ impl:
+ python:
+ function: runcmd_exit_code_is_not
- then: command is successful
- function: runcmd_exit_code_is_zero
+ impl:
+ python:
+ function: runcmd_exit_code_is_zero
- then: command fails
- function: runcmd_exit_code_is_nonzero
+ impl:
+ python:
+ function: runcmd_exit_code_is_nonzero
# Steps to examine stdout/stderr for exact content.
- then: stdout is exactly "(?P<text>.*)"
regex: true
- function: runcmd_stdout_is
+ impl:
+ python:
+ function: runcmd_stdout_is
-- then: "stdout isn't exactly \"(?P<text>.*)\""
+- then: 'stdout isn''t exactly "(?P<text>.*)"'
regex: true
- function: runcmd_stdout_isnt
+ impl:
+ python:
+ function: runcmd_stdout_isnt
- then: stderr is exactly "(?P<text>.*)"
regex: true
- function: runcmd_stderr_is
+ impl:
+ python:
+ function: runcmd_stderr_is
-- then: "stderr isn't exactly \"(?P<text>.*)\""
+- then: 'stderr isn''t exactly "(?P<text>.*)"'
regex: true
- function: runcmd_stderr_isnt
+ impl:
+ python:
+ function: runcmd_stderr_isnt
# Steps to examine stdout/stderr for sub-strings.
- then: stdout contains "(?P<text>.*)"
regex: true
- function: runcmd_stdout_contains
+ impl:
+ python:
+ function: runcmd_stdout_contains
-- then: "stdout doesn't contain \"(?P<text>.*)\""
+- then: 'stdout doesn''t contain "(?P<text>.*)"'
regex: true
- function: runcmd_stdout_doesnt_contain
+ impl:
+ python:
+ function: runcmd_stdout_doesnt_contain
- then: stderr contains "(?P<text>.*)"
regex: true
- function: runcmd_stderr_contains
+ impl:
+ python:
+ function: runcmd_stderr_contains
-- then: "stderr doesn't contain \"(?P<text>.*)\""
+- then: 'stderr doesn''t contain "(?P<text>.*)"'
regex: true
- function: runcmd_stderr_doesnt_contain
+ impl:
+ python:
+ function: runcmd_stderr_doesnt_contain
# Steps to match stdout/stderr against regular expressions.
- then: stdout matches regex (?P<regex>.*)
regex: true
- function: runcmd_stdout_matches_regex
+ impl:
+ python:
+ function: runcmd_stdout_matches_regex
- then: stdout doesn't match regex (?P<regex>.*)
regex: true
- function: runcmd_stdout_doesnt_match_regex
+ impl:
+ python:
+ function: runcmd_stdout_doesnt_match_regex
- then: stderr matches regex (?P<regex>.*)
regex: true
- function: runcmd_stderr_matches_regex
+ impl:
+ python:
+ function: runcmd_stderr_matches_regex
- then: stderr doesn't match regex (?P<regex>.*)
regex: true
- function: runcmd_stderr_doesnt_match_regex
+ impl:
+ python:
+ function: runcmd_stderr_doesnt_match_regex
diff --git a/share/python/lib/runcmd_test.yaml b/share/python/lib/runcmd_test.yaml
index 8ade220..2ad981e 100644
--- a/share/python/lib/runcmd_test.yaml
+++ b/share/python/lib/runcmd_test.yaml
@@ -1,5 +1,9 @@
- given: "executable script {filename} from {embedded}"
- function: create_script_from_embedded
+ impl:
+ python:
+ function: create_script_from_embedded
- when: "I prepend {dirname} to PATH"
- function: runcmd_prepend_to_path
+ impl:
+ python:
+ function: runcmd_prepend_to_path
diff --git a/share/rust/lib/datadir.yaml b/share/rust/lib/datadir.yaml
index acd4ad4..f4c313b 100644
--- a/share/rust/lib/datadir.yaml
+++ b/share/rust/lib/datadir.yaml
@@ -4,10 +4,14 @@
# of the capabilities are worth exporting as steps
- given: datadir has at least {bytes}B of space
- function: subplotlib::steplibrary::datadir::datadir_has_enough_space
+ impl:
+ rust:
+ function: subplotlib::steplibrary::datadir::datadir_has_enough_space
types:
bytes: uint
- given: datadir has at least {megabytes}M of space
- function: subplotlib::steplibrary::datadir::datadir_has_enough_space_megabytes
+ impl:
+ rust:
+ function: subplotlib::steplibrary::datadir::datadir_has_enough_space_megabytes
types:
megabytes: uint
diff --git a/share/rust/lib/files.yaml b/share/rust/lib/files.yaml
index 5fa4f45..cabda12 100644
--- a/share/rust/lib/files.yaml
+++ b/share/rust/lib/files.yaml
@@ -2,88 +2,138 @@
# These bind the files step library for subplotlib
- given: file {embedded_file}
- function: subplotlib::steplibrary::files::create_from_embedded
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::create_from_embedded
types:
embedded_file: file
- given: file {filename_on_disk} from {embedded_file}
- function: subplotlib::steplibrary::files::create_from_embedded_with_other_name
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::create_from_embedded_with_other_name
types:
embedded_file: file
- given: file (?P<filename>\S+) has modification time (?P<mtime>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})
regex: true
- function: subplotlib::steplibrary::files::touch_with_timestamp
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::touch_with_timestamp
types:
mtime: text
- when: I write "(?P<text>.*)" to file (?P<filename>\S+)
regex: true
- function: subplotlib::steplibrary::files::create_from_text
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::create_from_text
- when: I remember metadata for file {filename}
- function: subplotlib::steplibrary::files::remember_metadata
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::remember_metadata
- when: I touch file {filename}
- function: subplotlib::steplibrary::files::touch
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::touch
- then: file {filename} exists
- function: subplotlib::steplibrary::files::file_exists
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_exists
- then: file {filename} does not exist
- function: subplotlib::steplibrary::files::file_does_not_exist
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_does_not_exist
- then: only files (?P<filenames>.+) exist
- function: subplotlib::steplibrary::files::only_these_exist
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::only_these_exist
regex: true
- then: file (?P<filename>\S+) contains "(?P<data>.*)"
regex: true
- function: subplotlib::steplibrary::files::file_contains
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_contains
- then: file (?P<filename>\S+) matches regex /(?P<regex>.*)/
regex: true
- function: subplotlib::steplibrary::files::file_matches_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_matches_regex
- then: file (?P<filename>\S+) matches regex "(?P<regex>.*)"
regex: true
- function: subplotlib::steplibrary::files::file_matches_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_matches_regex
- then: files {filename1} and {filename2} match
- function: subplotlib::steplibrary::files::file_match
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::file_match
- then: file {filename} has same metadata as before
- function: subplotlib::steplibrary::files::has_remembered_metadata
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::has_remembered_metadata
- then: file {filename} has different metadata from before
- function: subplotlib::steplibrary::files::has_different_metadata
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::has_different_metadata
- then: file {filename} has changed from before
- function: subplotlib::steplibrary::files::has_different_metadata
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::has_different_metadata
- then: file {filename} has a very recent modification time
- function: subplotlib::steplibrary::files::mtime_is_recent
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::mtime_is_recent
- then: file {filename} has a very old modification time
- function: subplotlib::steplibrary::files::mtime_is_ancient
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::mtime_is_ancient
- given: a directory {path}
- function: subplotlib::steplibrary::files::make_directory
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::make_directory
- when: I create directory {path}
- function: subplotlib::steplibrary::files::make_directory
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::make_directory
- when: I remove directory {path}
- function: subplotlib::steplibrary::files::remove_directory
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::remove_directory
- then: directory {path} exists
- function: subplotlib::steplibrary::files::path_exists
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::path_exists
- then: directory {path} does not exist
- function: subplotlib::steplibrary::files::path_does_not_exist
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::path_does_not_exist
- then: directory {path} is empty
- function: subplotlib::steplibrary::files::path_is_empty
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::path_is_empty
- then: directory {path} is not empty
- function: subplotlib::steplibrary::files::path_is_not_empty
+ impl:
+ rust:
+ function: subplotlib::steplibrary::files::path_is_not_empty
diff --git a/share/rust/lib/runcmd.yaml b/share/rust/lib/runcmd.yaml
index fc2db6b..1043876 100644
--- a/share/rust/lib/runcmd.yaml
+++ b/share/rust/lib/runcmd.yaml
@@ -1,97 +1,141 @@
# Bindings for the runcmd steplibrary
- given: helper script {script} for runcmd
- function: subplotlib::steplibrary::runcmd::helper_script
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::helper_script
types:
script: file
- given: srcdir is in the PATH
- function: subplotlib::steplibrary::runcmd::helper_srcdir_path
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::helper_srcdir_path
- when: I run (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::run
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::run
- when: I run, in (?P<dirname>\S+), (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::run_in
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::run_in
- when: I try to run (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::try_to_run
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::try_to_run
- when: I try to run, in (?P<dirname>\S+), (?P<argv0>\S+)(?P<args>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::try_to_run_in
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::try_to_run_in
# Steps to examine exit code of latest command.
- then: exit code is {exit}
- function: subplotlib::steplibrary::runcmd::exit_code_is
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::exit_code_is
types:
exit: int
- then: exit code is not {exit}
- function: subplotlib::steplibrary::runcmd::exit_code_is_not
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::exit_code_is_not
types:
exit: int
- then: command is successful
- function: subplotlib::steplibrary::runcmd::exit_code_is_zero
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::exit_code_is_zero
- then: command fails
- function: subplotlib::steplibrary::runcmd::exit_code_is_nonzero
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::exit_code_is_nonzero
# Steps to examine stdout/stderr for exact content.
- then: stdout is exactly "(?P<text>.*)"
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_is
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_is
- then: 'stdout isn''t exactly "(?P<text>.*)"'
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_isnt
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_isnt
- then: stderr is exactly "(?P<text>.*)"
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_is
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_is
- then: 'stderr isn''t exactly "(?P<text>.*)"'
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_isnt
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_isnt
# Steps to examine stdout/stderr for sub-strings.
- then: stdout contains "(?P<text>.*)"
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_contains
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_contains
- then: 'stdout doesn''t contain "(?P<text>.*)"'
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_doesnt_contain
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_doesnt_contain
- then: stderr contains "(?P<text>.*)"
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_contains
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_contains
- then: 'stderr doesn''t contain "(?P<text>.*)"'
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_doesnt_contain
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_doesnt_contain
# Steps to match stdout/stderr against regular expressions.
- then: stdout matches regex (?P<regex>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_matches_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_matches_regex
- then: stdout doesn't match regex (?P<regex>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::stdout_doesnt_match_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stdout_doesnt_match_regex
- then: stderr matches regex (?P<regex>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_matches_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_matches_regex
- then: stderr doesn't match regex (?P<regex>.*)
regex: true
- function: subplotlib::steplibrary::runcmd::stderr_doesnt_match_regex
+ impl:
+ rust:
+ function: subplotlib::steplibrary::runcmd::stderr_doesnt_match_regex
diff --git a/src/bindings.rs b/src/bindings.rs
index 5b8d013..9282155 100644
--- a/src/bindings.rs
+++ b/src/bindings.rs
@@ -10,6 +10,7 @@ use serde_aux::prelude::*;
use std::collections::HashMap;
use std::fmt::Debug;
+use std::ops::Deref;
use std::path::Path;
use std::str::FromStr;
use std::sync::Arc;
@@ -206,8 +207,8 @@ impl Binding {
}
/// Retrieve a particular implementation by name
- pub fn step_impl(&self, template: &str) -> Option<Arc<BindingImpl>> {
- self.impls.get(template).cloned()
+ pub fn step_impl(&self, _template: &str) -> Option<Arc<BindingImpl>> {
+ self.impls.values().next().cloned()
}
/// Return the compiled regular expression for the pattern of the
@@ -399,12 +400,33 @@ impl Default for Bindings {
}
#[derive(Debug, Deserialize)]
+struct ParsedImpl {
+ function: String,
+ cleanup: Option<String>,
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(transparent)]
+struct ParsedImplWrapper {
+ #[serde(deserialize_with = "deserialize_struct_case_insensitive")]
+ pimpl: ParsedImpl,
+}
+
+impl Deref for ParsedImplWrapper {
+ type Target = ParsedImpl;
+
+ fn deref(&self) -> &Self::Target {
+ &self.pimpl
+ }
+}
+
+#[derive(Debug, Deserialize)]
struct ParsedBinding {
given: Option<String>,
when: Option<String>,
then: Option<String>,
- function: String,
- cleanup: Option<String>,
+ #[serde(default, rename = "impl")]
+ impls: HashMap<String, ParsedImplWrapper>,
regex: Option<bool>,
#[serde(default)]
case_sensitive: bool,
@@ -549,7 +571,9 @@ fn from_hashmap(parsed: &ParsedBinding) -> Result<Binding> {
let mut ret = Binding::new(kind, &pattern, parsed.case_sensitive, types)?;
event!(Level::TRACE, "Binding parsed OK");
- ret.add_impl("", &parsed.function, parsed.cleanup.as_deref());
+ for (template, pimpl) in &parsed.impls {
+ ret.add_impl(template, &pimpl.function, pimpl.cleanup.as_deref());
+ }
Ok(ret)
}
@@ -589,16 +613,26 @@ mod test_bindings {
fn adds_from_yaml() {
let yaml = "
- GIVEN: I am Tomjon
- function: set_name
+ impl:
+ python:
+ function: set_name
- when: I declare myself king
- Function: declare_king
+ impl:
+ python:
+ Function: declare_king
- tHEn: there is applause
- function: check_for_applause
+ impl:
+ python:
+ function: check_for_applause
- given: you are alice
- function: other_name
+ impl:
+ python:
+ function: other_name
case_sensitive: true
- then: the total is {total}
- function: check_total
+ impl:
+ python:
+ function: check_total
types:
total: word
";
@@ -619,7 +653,9 @@ mod test_bindings {
let yaml = "
- Given: I am Tomjon
wheN: I am indeed Tomjon
- FUNCTION: set_name
+ impl:
+ python:
+ FUNCTION: set_name
";
match Bindings::new().add_from_yaml(yaml) {
Ok(_) => unreachable!(),
@@ -632,7 +668,9 @@ mod test_bindings {
fn typemap_must_match_pattern() {
let yaml = "
- then: you are {age:word} years old
- function: check_age
+ impl:
+ python:
+ function: check_age
types:
age: number
";
diff --git a/subplot.md b/subplot.md
index b7169c7..aef5808 100644
--- a/subplot.md
+++ b/subplot.md
@@ -654,16 +654,24 @@ expresssions ([PCRE][]).
~~~{.yaml .numberLines}
- given: "a standard setup"
- function: create_standard_setup
+ impl:
+ python:
+ function: create_standard_setup
- when: "{thing} happens"
- function: make_thing_happen
+ impl:
+ python:
+ function: make_thing_happen
types:
thing: word
- when: "I say (?P<sentence>.+) with a smile"
regex: true
- function: speak
+ impl:
+ python:
+ function: speak
- then: "everything is OK"
- function: check_everything_is_ok
+ impl:
+ python:
+ function: check_everything_is_ok
~~~
In the example above, there are four bindings:
@@ -925,17 +933,29 @@ then bar was done
~~~{#b.yaml .file .yaml .numberLines}
- given: precondition foo
- function: precond_foo
+ impl:
+ python:
+ function: precond_foo
- when: I do bar
- function: do_bar
+ impl:
+ python:
+ function: do_bar
- when: I do foobar
- function: do_foobar
+ impl:
+ python:
+ function: do_foobar
- then: bar was done
- function: bar_was_done
+ impl:
+ python:
+ function: bar_was_done
- then: foobar was done
- function: foobar_was_done
+ impl:
+ python:
+ function: foobar_was_done
- given: file {filename}
- function: provide_file
+ impl:
+ python:
+ function: provide_file
types:
filename: file
~~~
@@ -1152,14 +1172,20 @@ test this for every language template we support.
~~~{#cleanup.yaml .file .yaml .numberLines}
- given: foo
- function: foo
- cleanup: foo_cleanup
+ impl:
+ python:
+ function: foo
+ cleanup: foo_cleanup
- given: bar
- function: bar
- cleanup: bar_cleanup
+ impl:
+ python:
+ function: bar
+ cleanup: bar_cleanup
- given: failure
- function: failure
- cleanup: failure_cleanup
+ impl:
+ python:
+ function: failure
+ cleanup: failure_cleanup
~~~
~~~{#cleanup.py .file .python .numberLines}
@@ -1370,7 +1396,9 @@ then TMPDIR is set
~~~{#tmpdir.yaml .file .yaml .numberLines}
- then: TMPDIR is set
- function: tmpdir_is_set
+ impl:
+ python:
+ function: tmpdir_is_set
~~~
~~~{#tmpdir.py .file .python .numberLines}
@@ -1420,7 +1448,9 @@ given I am Tomjon
~~~{#simplepattern.yaml .file .yaml .numberLines}
- given: I am {name}
- function: func
+ impl:
+ python:
+ function: func
~~~
~~~{#capture.py .file .python .numberLines}
@@ -1462,7 +1492,9 @@ given I* am Tomjon
~~~{#confusedpattern.yaml .file .yaml .numberLines}
- given: I* am {name}
- function: func
+ impl:
+ python:
+ function: func
~~~
### Simple patterns with regex metacharacters: allowed case
@@ -1493,7 +1525,9 @@ given I* am Tomjon
~~~{#confusedbutok.yaml .file .yaml .numberLines}
- given: I* am {name}
- function: func
+ impl:
+ python:
+ function: func
regex: false
~~~
@@ -1528,7 +1562,9 @@ given I am Tomjon
~~~{#regex.yaml .file .yaml .numberLines}
- given: I am (?P<name>\S+)
- function: func
+ impl:
+ python:
+ function: func
regex: true
~~~
@@ -1577,10 +1613,14 @@ then expanded "${foo}" is bar
~~~{#values.yaml .file .yaml .numberLines}
- when: I remember {name} as {value}
- function: remember
+ impl:
+ python:
+ function: remember
- then: expanded "{actual}" is {expected}
- function: check
+ impl:
+ python:
+ function: check
~~~
~~~{#values.py .file .python .numberLines}
@@ -1643,7 +1683,9 @@ then environment variable FOO is set to "bar"
~~~{#env.yaml .file .yaml .numberLines}
- then: environment variable {name} is set to "{value:text}"
- function: is_set_to
+ impl:
+ python:
+ function: is_set_to
~~~
~~~{#env.py .file .python .numberLines}
@@ -2541,12 +2583,18 @@ binding.
```{#badbindings.yaml .file .yaml}
- given: a binding
- function: a_binding
+ impl:
+ python:
+ function: a_binding
- given: a (?:broken)? binding
- function: a_broken_binding
+ impl:
+ python:
+ function: a_broken_binding
regex: true
- given: a capitalised Binding
- function: os.getcwd
+ impl:
+ python:
+ function: os.getcwd
case_sensitive: true
```
@@ -2618,9 +2666,13 @@ given a binding
~~~{#twobindings.yaml .file .yaml}
- given: a {xyzzy}
- function: a_function
+ impl:
+ python:
+ function: a_function
- given: a {plugh}
- function: a_function
+ impl:
+ python:
+ function: a_function
~~~
~~~{#a_function.py .file .python}
diff --git a/subplot.yaml b/subplot.yaml
index c7c0c4e..229cc7d 100644
--- a/subplot.yaml
+++ b/subplot.yaml
@@ -1,48 +1,71 @@
- given: an installed subplot
- function: install_subplot
- cleanup: uninstall_subplot
+ impl:
+ python:
+ function: install_subplot
+ cleanup: uninstall_subplot
- then: scenario "(?P<name>.+)" was run
- function: scenario_was_run
+ impl:
+ python:
+ function: scenario_was_run
regex: true
- then: scenario "(?P<name>.+)" was not run
- function: scenario_was_not_run
+ impl:
+ python:
+ function: scenario_was_not_run
regex: true
- then: step "(?P<keyword>given|when|then) (?P<name>.+)" was run
- function: step_was_run
+ impl:
+ python:
+ function: step_was_run
regex: true
- then: step "(?P<keyword1>given|when|then) (?P<name1>.+)" was run, and then step "(?P<keyword2>given|when|then) (?P<name2>.+)"
- function: step_was_run_and_then
+ impl:
+ python:
+ function: step_was_run_and_then
regex: true
- then: cleanup for "(?P<keyword1>given|when|then) (?P<name1>.+)" was run, and then for "(?P<keyword2>given|when|then) (?P<name2>.+)"
- function: cleanup_was_run
+ impl:
+ python:
+ function: cleanup_was_run
regex: true
- then: cleanup for "(?P<keyword>given|when|then) (?P<name>.+)" was not run
- function: cleanup_was_not_run
+ impl:
+ python:
+ function: cleanup_was_not_run
regex: true
-
- then: JSON output matches {filename}
- function: json_output_matches_file
+ impl:
+ python:
+ function: json_output_matches_file
- then: "{filename} does not end in a newline"
- function: file_ends_in_zero_newlines
+ impl:
+ python:
+ function: file_ends_in_zero_newlines
- then: "{filename} ends in one newline"
- function: file_ends_in_one_newline
+ impl:
+ python:
+ function: file_ends_in_one_newline
- then: "{filename} ends in two newlines"
- function: file_ends_in_two_newlines
+ impl:
+ python:
+ function: file_ends_in_two_newlines
# In order to cope with low granularity filesystems, sometimes we need to wait
# for things to happen
- when: I wait until (?P<delay>\d+) seconds? has passed
- function: sleep_seconds
+ impl:
+ python:
+ function: sleep_seconds
regex: true
types:
delay: uint
@@ -50,10 +73,16 @@
# The following are purely descriptive steps and are not used to test anything
- given: the necessary starting conditions
- function: do_nothing
+ impl:
+ python:
+ function: do_nothing
- when: I do the required actions
- function: do_nothing
+ impl:
+ python:
+ function: do_nothing
- then: the desired outcome is achieved
- function: do_nothing
+ impl:
+ python:
+ function: do_nothing
diff --git a/subplotlib/subplotlib.yaml b/subplotlib/subplotlib.yaml
index 78090c3..f92ff24 100644
--- a/subplotlib/subplotlib.yaml
+++ b/subplotlib/subplotlib.yaml
@@ -1,20 +1,32 @@
- given: a counter starting at {initial}
- function: a_trivial_setup
- cleanup: a_trivial_cleanup
+ impl:
+ rust:
+ function: a_trivial_setup
+ cleanup: a_trivial_cleanup
types:
initial: int
- when: the counter is incremented
- function: increment_counter
+ impl:
+ rust:
+ function: increment_counter
- then: the counter is {num}
- function: check_counter
+ impl:
+ rust:
+ function: check_counter
types:
num: number
- given: I have read the file {file} into {somename}
- function: acquire_file_content
+ impl:
+ rust:
+ function: acquire_file_content
types:
file: file
somename: text
- when: I look at {somename}
- function: remember_target
+ impl:
+ rust:
+ function: remember_target
- then: I see "{text:text}"
- function: check_contents
+ impl:
+ rust:
+ function: check_contents