From d0c991a5f55601c87209a6d2c1d7e7efdd49f486 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Thu, 4 Aug 2022 20:37:26 +0200 Subject: [PATCH 01/10] Add test for custom conditions Add a test for custom conditions: * two without arguments * two requiring an argument The companion script shows how the condition work when they match, when they don't match, and when they match but are negated. --- testscript/testdata/custom_conditions.txt | 67 +++++++++++++++++++++++ testscript/testscript_test.go | 24 ++++++++ 2 files changed, 91 insertions(+) create mode 100644 testscript/testdata/custom_conditions.txt diff --git a/testscript/testdata/custom_conditions.txt b/testscript/testdata/custom_conditions.txt new file mode 100644 index 00000000..8c1018f3 --- /dev/null +++ b/testscript/testdata/custom_conditions.txt @@ -0,0 +1,67 @@ +[!exec:echo] skip + +env upper_word=ABCD +env lower_word=abcd + +[always_true] exec echo 'this is true' +stdout 'this is true' + +exec echo '' + +[!always_true] exec echo 'this is true' +! stdout . + +exec echo '' + +[always_false] exec echo 'this is false' +! stdout . + +exec echo '' + +[!always_false] exec echo 'this is false' +stdout 'this is false' + +exec echo '' + +[is_upper:ABCD] exec echo 'it is upper' +stdout 'it is upper' + +exec echo '' + +[is_upper:$upper_word] exec echo 'it is again upper' +stdout 'it is again upper' + +exec echo '' + +[is_upper:abcd] exec echo 'it is upper' +! stdout . + +exec echo '' + +[is_upper:$lower_word] exec echo 'it is lower' +! stdout . + +exec echo '' + +[!is_upper:ABCD] exec echo 'it is upper' +! stdout . + +exec echo '' + +[is_lower:abcd] exec echo 'it is lower' +stdout 'it is lower' + +exec echo '' + +[is_lower:$lower_word] exec echo 'it is again lower' +stdout 'it is again lower' + +exec echo '' + +[is_lower:ABCD] exec echo 'it is lower' +! stdout . + +exec echo '' + +[!is_lower:$lower_word] exec echo 'it is lower' +! stdout . diff --git a/testscript/testscript_test.go b/testscript/testscript_test.go index e8faee04..ab162bc1 100644 --- a/testscript/testscript_test.go +++ b/testscript/testscript_test.go @@ -222,6 +222,30 @@ func TestScripts(t *testing.T) { } }, }, + Condition: func(cond string) (bool, error) { + // Assume condition name and args are separated by colon (":") + args := strings.Split(cond, ":") + // Empty condition is already managed in testscript.run() + name := args[0] + switch name { + case "is_upper": + if len(args) < 2 { + return false, fmt.Errorf("syntax: is_upper:word") + } + return strings.ToUpper(args[1]) == args[1], nil + case "is_lower": + if len(args) < 2 { + return false, fmt.Errorf("syntax: is_lower:word") + } + return strings.ToLower(args[1]) == args[1], nil + case "always_true": + return true, nil + case "always_false": + return false, nil + default: + return false, fmt.Errorf("unrecognized condition %s", name) + } + }, Setup: func(env *Env) error { infos, err := ioutil.ReadDir(env.WorkDir) if err != nil { From 4c3f2b91f98740168635910533db10a85fc78ab3 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Thu, 4 Aug 2022 20:40:59 +0200 Subject: [PATCH 02/10] Add custom condition example in the docs --- go.mod | 6 ++---- testscript/doc.go | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 3da36bc0..803a09d3 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ -module github.com/rogpeppe/go-internal +module github.com/datacharmer/go-internal -go 1.17 - -require github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e +go 1.18 diff --git a/testscript/doc.go b/testscript/doc.go index 28db63e7..653492f8 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -120,6 +120,23 @@ when testing.Short() is false. Additional conditions can be added by passing a function to Params.Condition. +A simple example: + + Condition: func(cond string) (bool, error) { + switch cond { + case "always_true": + return true, nil + case "always_false": + return false, nil + default: + return false, fmt.Errorf("unrecognized condition %s", cond) + } + }, + +For more complex conditions that require parameters (such as [exec:program_name]) you can +split the `cond` argument and evaluate the components. The function `TestScripts` in testscript_test.go +shows such an approach. + The predefined commands are: - cd dir From 0d6efa642d64ff624ed3fc5a1b477a711d05f153 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Thu, 4 Aug 2022 20:46:59 +0200 Subject: [PATCH 03/10] Restore go.mod --- go.mod | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 803a09d3..3da36bc0 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ -module github.com/datacharmer/go-internal +module github.com/rogpeppe/go-internal -go 1.18 +go 1.17 + +require github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e From 4b4de17480957759c52444e93a7bf28fcd3e8038 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 05:15:04 +0200 Subject: [PATCH 04/10] Improve custom condition example --- testscript/doc.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/testscript/doc.go b/testscript/doc.go index 653492f8..1e8cdf6a 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -120,22 +120,34 @@ when testing.Short() is false. Additional conditions can be added by passing a function to Params.Condition. -A simple example: +An example: Condition: func(cond string) (bool, error) { - switch cond { + // Assume condition name and args are separated by colon (":") + args := strings.Split(cond, ":") + // Empty condition is already managed in testscript.run() + name := args[0] + switch name { + case "is_upper": + if len(args) < 2 { + return false, fmt.Errorf("syntax: [is_upper:word]") + } + return strings.ToUpper(args[1]) == args[1], nil case "always_true": return true, nil - case "always_false": - return false, nil default: - return false, fmt.Errorf("unrecognized condition %s", cond) + return false, fmt.Errorf("unrecognized condition %s", name) } }, -For more complex conditions that require parameters (such as [exec:program_name]) you can -split the `cond` argument and evaluate the components. The function `TestScripts` in testscript_test.go -shows such an approach. +With the conditions so defined, you can use them as follows: + + env upper_word=ABCD + env lower_word=abcd + # the first two conditions will allow the 'echo' command to run. The third one will go silent. + [always_true] exec echo 'this is true' + [is_upper:$upper_word] exec echo 'found an uppercase word' + [is_upper:$lower_word] exec echo 'found an uppercase word' The predefined commands are: From 90696b0505cf6b184926eca120c2688a33f3d5e3 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 05:15:35 +0200 Subject: [PATCH 05/10] Improve error message --- testscript/testscript_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testscript/testscript_test.go b/testscript/testscript_test.go index ab162bc1..79d576ce 100644 --- a/testscript/testscript_test.go +++ b/testscript/testscript_test.go @@ -230,12 +230,12 @@ func TestScripts(t *testing.T) { switch name { case "is_upper": if len(args) < 2 { - return false, fmt.Errorf("syntax: is_upper:word") + return false, fmt.Errorf("syntax: [is_upper:word]") } return strings.ToUpper(args[1]) == args[1], nil case "is_lower": if len(args) < 2 { - return false, fmt.Errorf("syntax: is_lower:word") + return false, fmt.Errorf("syntax: [is_lower:word]") } return strings.ToLower(args[1]) == args[1], nil case "always_true": From 03e188167ce767e1c5cdcf5c4b2b775567f04688 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 14:18:07 +0200 Subject: [PATCH 06/10] Improve docs example for custom conditions --- testscript/doc.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/testscript/doc.go b/testscript/doc.go index 1e8cdf6a..0c372be7 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -121,33 +121,31 @@ when testing.Short() is false. Additional conditions can be added by passing a function to Params.Condition. An example: - Condition: func(cond string) (bool, error) { // Assume condition name and args are separated by colon (":") args := strings.Split(cond, ":") // Empty condition is already managed in testscript.run() name := args[0] switch name { - case "is_upper": + case "exists": if len(args) < 2 { - return false, fmt.Errorf("syntax: [is_upper:word]") + return false, fmt.Errorf("syntax: [exists:file_name]") } - return strings.ToUpper(args[1]) == args[1], nil - case "always_true": - return true, nil + _, err := os.Stat(args[1]) + return !errors.Is(err, fs.ErrNotExist), nil + case "long": + return os.Getenv("TEST_LONG") != "", nil default: return false, fmt.Errorf("unrecognized condition %s", name) } }, With the conditions so defined, you can use them as follows: - - env upper_word=ABCD - env lower_word=abcd - # the first two conditions will allow the 'echo' command to run. The third one will go silent. - [always_true] exec echo 'this is true' - [is_upper:$upper_word] exec echo 'found an uppercase word' - [is_upper:$lower_word] exec echo 'found an uppercase word' + env file_name=/path/to/filename + [exists:$file_name] exec echo 'file was found' + env loops=1 + [long] env loops=3 + exec do_something $loops The predefined commands are: From 10e516a66031d9df020f48568d758380d61a87b0 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 14:27:12 +0200 Subject: [PATCH 07/10] Add explanation about custom condition usage --- testscript/doc.go | 1 + 1 file changed, 1 insertion(+) diff --git a/testscript/doc.go b/testscript/doc.go index 0c372be7..e86dbdfe 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -119,6 +119,7 @@ A condition can be negated: [!short] means to run the rest of the line when testing.Short() is false. Additional conditions can be added by passing a function to Params.Condition. +The function will only be called when all built-in conditions have been checked for. An example: Condition: func(cond string) (bool, error) { From 07717e8000d29ee5db54db220ee08c4610d9394d Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 22:17:40 +0200 Subject: [PATCH 08/10] Remove unnecessary comment from test and example --- testscript/doc.go | 1 - testscript/testscript_test.go | 1 - 2 files changed, 2 deletions(-) diff --git a/testscript/doc.go b/testscript/doc.go index e86dbdfe..ed4b9858 100644 --- a/testscript/doc.go +++ b/testscript/doc.go @@ -125,7 +125,6 @@ An example: Condition: func(cond string) (bool, error) { // Assume condition name and args are separated by colon (":") args := strings.Split(cond, ":") - // Empty condition is already managed in testscript.run() name := args[0] switch name { case "exists": diff --git a/testscript/testscript_test.go b/testscript/testscript_test.go index 79d576ce..e7bdd487 100644 --- a/testscript/testscript_test.go +++ b/testscript/testscript_test.go @@ -225,7 +225,6 @@ func TestScripts(t *testing.T) { Condition: func(cond string) (bool, error) { // Assume condition name and args are separated by colon (":") args := strings.Split(cond, ":") - // Empty condition is already managed in testscript.run() name := args[0] switch name { case "is_upper": From 9d149101d4bd57e1a4d86f679d8437dba5023d7e Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Fri, 5 Aug 2022 22:18:33 +0200 Subject: [PATCH 09/10] Add test for custom condition errors --- .../testdata/custom_conditions_errors.txt | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 testscript/testdata/custom_conditions_errors.txt diff --git a/testscript/testdata/custom_conditions_errors.txt b/testscript/testdata/custom_conditions_errors.txt new file mode 100644 index 00000000..d47b3446 --- /dev/null +++ b/testscript/testdata/custom_conditions_errors.txt @@ -0,0 +1,72 @@ +env GOPATH=$WORK +env GOCACHE=$WORK/.cache + +[!exec:echo] skip +cd cond_errors +exec go mod tidy +! exec go test -run TestConditionErrors/is_upper-no-parameter +stdout 'FAIL' +stdout 'syntax: \[is_upper:word\]' + +! exec go test -run TestConditionErrors/is_lower-no-parameter +stdout 'FAIL' +stdout 'syntax: \[is_lower:word\]' + +! exec go test -run TestConditionErrors/unrecognized +stdout 'FAIL' +stdout 'unrecognized condition something' + +-- cond_errors/main_test.go -- +package condition_errors + +import ( + "fmt" + "strings" + "testing" + + "github.com/rogpeppe/go-internal/testscript" +) + +func TestConditionErrors(t *testing.T) { + testscript.Run(t, testscript.Params{ + Dir: "testdata", + Condition: func(cond string) (bool, error) { + // Assume condition name and args are separated by colon (":") + args := strings.Split(cond, ":") + name := args[0] + switch name { + case "is_upper": + if len(args) < 2 { + return false, fmt.Errorf("syntax: [is_upper:word]") + } + return strings.ToUpper(args[1]) == args[1], nil + case "is_lower": + if len(args) < 2 { + return false, fmt.Errorf("syntax: [is_lower:word]") + } + return strings.ToLower(args[1]) == args[1], nil + case "always_true": + return true, nil + case "always_false": + return false, nil + default: + return false, fmt.Errorf("unrecognized condition %s", name) + } + }, + }) +} +-- cond_errors/go.mod -- +module condition_errors + +go 1.18 + +require ( + github.com/rogpeppe/go-internal v1.8.1 +) + +-- cond_errors/testdata/is_upper-no-parameter.txt -- +[is_upper] exec echo '' +-- cond_errors/testdata/is_lower-no-parameter.txt -- +[is_lower] exec echo '' +-- cond_errors/testdata/unrecognized.txt -- +[something] exec echo '' From 9f43ce38a951d1e647eeb021dad98e5123b0a336 Mon Sep 17 00:00:00 2001 From: Giuseppe Maxia Date: Tue, 30 Aug 2022 11:36:13 +0200 Subject: [PATCH 10/10] Update custom_conditions_errors test --- testscript/testdata/custom_conditions_errors.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testscript/testdata/custom_conditions_errors.txt b/testscript/testdata/custom_conditions_errors.txt index d47b3446..65301bde 100644 --- a/testscript/testdata/custom_conditions_errors.txt +++ b/testscript/testdata/custom_conditions_errors.txt @@ -61,7 +61,7 @@ module condition_errors go 1.18 require ( - github.com/rogpeppe/go-internal v1.8.1 + github.com/rogpeppe/go-internal v1.9.0 ) -- cond_errors/testdata/is_upper-no-parameter.txt --