Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go/oasis-test-runner: List all available scenarios #3044

Merged
merged 3 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changelog/3044.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/oasis-test-runner/cmd/common: Give verbose error when scenario is not found

List all available scenarios if `oasis-test-runner` command is invoked with an
unknown scenario.
7 changes: 3 additions & 4 deletions go/oasis-test-runner/cmd/cmp/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/spf13/viper"

"github.com/oasisprotocol/oasis-core/go/common/logging"
nodeCommon "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/metrics"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/cmd/common"
)
Expand Down Expand Up @@ -120,7 +119,7 @@ func getDuration(ctx context.Context, test string, bi *model.SampleStream) (floa
query := fmt.Sprintf("%s %s == 1.0", metrics.MetricUp, bi.Metric.String())
result, warnings, err := v1api.QueryRange(ctx, query, r)
if err != nil {
nodeCommon.EarlyLogAndExit(fmt.Errorf("error querying Prometheus: %w", err))
return 0, 0, fmt.Errorf("error querying Prometheus: %w", err)
}
if len(warnings) > 0 {
cmpLogger.Warn("warnings while querying Prometheus", "warnings", warnings)
Expand Down Expand Up @@ -206,7 +205,7 @@ func getSummableMetric(ctx context.Context, metric string, test string, bi *mode

result, warnings, err := v1api.Query(ctx, query, t)
if err != nil {
nodeCommon.EarlyLogAndExit(fmt.Errorf("error querying Prometheus: %w", err))
return 0, 0, fmt.Errorf("error querying Prometheus: %w", err)
}
if len(warnings) > 0 {
cmpLogger.Warn("warnings while querying Prometheus", "warnings", warnings)
Expand Down Expand Up @@ -256,7 +255,7 @@ func getNetwork(ctx context.Context, test string, bi *model.SampleStream) (float
query := fmt.Sprintf("(%s %s)", rxtx, labels.String())
result, warnings, err := v1api.QueryRange(ctx, query, r)
if err != nil {
nodeCommon.EarlyLogAndExit(fmt.Errorf("error querying Prometheus: %w", err))
return 0, 0, fmt.Errorf("error querying Prometheus: %w", err)
}
if len(warnings) > 0 {
cmpLogger.Warn("warnings while querying Prometheus", "warnings", warnings)
Expand Down
10 changes: 10 additions & 0 deletions go/oasis-test-runner/cmd/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package common

import (
"fmt"
"sort"
"strings"

"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario"
Expand Down Expand Up @@ -33,6 +34,15 @@ func GetScenarios() map[string]scenario.Scenario {
return scenarios
}

// GetScenarioNames returns the names of all scenarios.
func GetScenarioNames() (names []string) {
tjanez marked this conversation as resolved.
Show resolved Hide resolved
for name := range scenarios {
names = append(names, name)
}
sort.Strings(names)
return
}

// GetDefaultScenarios returns all registered default scenarios.
//
// This function *is not* thread-safe.
Expand Down
14 changes: 8 additions & 6 deletions go/oasis-test-runner/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func RootCmd() *cobra.Command {
// Execute spawns the main entry point after handing the config file.
func Execute() {
if err := rootCmd.Execute(); err != nil {
nodeCommon.EarlyLogAndExit(err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nodeCommon.EarlyLogAndExit() prints the error to stderr:

// EarlyLogAndExit logs the error and exits.
//
// Note: This routine should only be used prior to the logging system
// being initialized.
func EarlyLogAndExit(err error) {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

which results in the same error message being outputted twice.

For example:

$ .buildkite/scripts/test_e2e.sh --test storage-sync
+ WORKDIR=/home/tadej/Oasis/oasis-core
+ runtime_target=default
+ [[ '' == \i\n\t\e\l\-\s\g\x ]]
+ [[ '' != '' ]]
+ node_binary=/home/tadej/Oasis/oasis-core/go/oasis-node/oasis-node
+ test_runner_binary=/home/tadej/Oasis/oasis-core/go/oasis-test-runner/oasis-test-runner
+ [[ '' != '' ]]
+ ias_mock=true
+ set +x
+ /home/tadej/Oasis/oasis-core/go/oasis-test-runner/oasis-test-runner --basedir.no_cleanup --e2e.node.binary /home/tadej/Oasis/oasis-core/go/oasis-node/oasis-node --e2e/runtime.client.binary_dir /home/tadej/Oasis/oasis-core/target/default/debug --e2e/runtime.runtime.binary_dir /home/tadej/Oasis/oasis-core/target/default/debug --e2e/runtime.runtime.loader /home/tadej/Oasis/oasis-core/target/default/debug/oasis-core-runtime-loader --e2e/runtime.tee_hardware '' --e2e/runtime.ias.mock=true --remote-signer.binary /home/tadej/Oasis/oasis-core/go/oasis-remote-signer/oasis-remote-signer --log.level info --test storage-sync
level=error module=test-runner caller=root.go:279 ts=2020-06-24T08:24:40.945179021Z msg="unknown scenario" scenario=storage-sync
Error: root: unknown scenario: storage-sync
Available scenarios:
e2e/identity-cli
e2e/runtime/byzantine/executor-honest
e2e/runtime/byzantine/executor-straggler
e2e/runtime/byzantine/executor-wrong
e2e/runtime/byzantine/merge-honest
e2e/runtime/byzantine/merge-straggler
e2e/runtime/byzantine/merge-wrong
e2e/runtime/debond
e2e/runtime/dump-restore
e2e/runtime/early-query
e2e/runtime/gas-fees/runtimes
e2e/runtime/gas-fees/staking
e2e/runtime/gas-fees/staking-dump-restore
e2e/runtime/halt-restore
e2e/runtime/keymanager-replication
e2e/runtime/keymanager-restart
e2e/runtime/keymanager-upgrade
e2e/runtime/late-start
e2e/runtime/multiple-runtimes
e2e/runtime/node-shutdown
e2e/runtime/node-upgrade
e2e/runtime/node-upgrade-cancel
e2e/runtime/registry-cli
e2e/runtime/runtime
e2e/runtime/runtime-dynamic
e2e/runtime/runtime-encryption
e2e/runtime/runtime-prune
e2e/runtime/sentry
e2e/runtime/sentry-encryption
e2e/runtime/stake-cli
e2e/runtime/storage-sync
e2e/runtime/txsource-multi
e2e/runtime/txsource-multi-short
remote-signer/basic
root: unknown scenario: storage-sync
Available scenarios:
e2e/identity-cli
e2e/runtime/byzantine/executor-honest
e2e/runtime/byzantine/executor-straggler
e2e/runtime/byzantine/executor-wrong
e2e/runtime/byzantine/merge-honest
e2e/runtime/byzantine/merge-straggler
e2e/runtime/byzantine/merge-wrong
e2e/runtime/debond
e2e/runtime/dump-restore
e2e/runtime/early-query
e2e/runtime/gas-fees/runtimes
e2e/runtime/gas-fees/staking
e2e/runtime/gas-fees/staking-dump-restore
e2e/runtime/halt-restore
e2e/runtime/keymanager-replication
e2e/runtime/keymanager-restart
e2e/runtime/keymanager-upgrade
e2e/runtime/late-start
e2e/runtime/multiple-runtimes
e2e/runtime/node-shutdown
e2e/runtime/node-upgrade
e2e/runtime/node-upgrade-cancel
e2e/runtime/registry-cli
e2e/runtime/runtime
e2e/runtime/runtime-dynamic
e2e/runtime/runtime-encryption
e2e/runtime/runtime-prune
e2e/runtime/sentry
e2e/runtime/sentry-encryption
e2e/runtime/stake-cli
e2e/runtime/storage-sync
e2e/runtime/txsource-multi
e2e/runtime/txsource-multi-short
remote-signer/basic

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who prints the first error message, does cobra do that internally?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Cobra does that in ExecuteC():

// If root command has SilentErrors flagged,
// all subcommands should respect it
if !cmd.SilenceErrors && !c.SilenceErrors {
	c.Println("Error:", err.Error())
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like our helper better as it prints to stderr while cobra seems to print to stdout? Could we instead set SilenceErrors (maybe this needs to be done in other places as well as we use EarlyLogAndExit everywhere)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like our helper better as it prints to stderr while cobra seems to print to stdout?

Cobra's Command.Println() defaults to printing to stderr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have this EarlyLogAndExit at all then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it is still useful for cases where we want to exit and print an error before we execute Cobra's Execute().

I found two such cases in go/oasis-test-runner:

I've removed other uses in go/oasis-test-runner.

For other parts of the code base, I can file an issue to systematically check that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For other parts of the code base, I can file an issue to systematically check that.

Done: #3048.

os.Exit(1)
}
}

Expand Down Expand Up @@ -268,18 +268,20 @@ func runRoot(cmd *cobra.Command, args []string) error {
defer rootEnv.Cleanup()
logger := logging.GetLogger("test-runner")

// Enumerate requested test cases.
// Enumerate requested scenarios.
toRun := common.GetDefaultScenarios() // Run all default scenarios if not set.
if vec := viper.GetStringSlice(common.CfgTest); len(vec) > 0 {
toRun = nil
for _, v := range vec {
n := strings.ToLower(v)
name := strings.ToLower(v)
scenario, ok := common.GetScenarios()[v]
if !ok {
logger.Error("unknown test case",
"test", n,
logger.Error("unknown scenario",
"scenario", name,
)
return fmt.Errorf("root: unknown scenario: %s\nAvailable scenarios:\n%s",
name, strings.Join(common.GetScenarioNames(), "\n"),
)
return fmt.Errorf("root: unknown test case: %s", n)
}
toRun = append(toRun, scenario)
}
Expand Down