Skip to content

Commit

Permalink
Merge pull request #2848 from oasislabs/matevz/feature/json_fixtures
Browse files Browse the repository at this point in the history
oasis-net-runner: Add support for loading fixtures from JSON
  • Loading branch information
matevz authored Apr 24, 2020
2 parents 1fcdd59 + b2b5339 commit e9945c8
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 39 deletions.
4 changes: 4 additions & 0 deletions .changelog/2848.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
`oasis-net-runner`: `--net.*` flags renamed to `--fixture.default.*`

For example `--net.node.binary mynode/oasis-node` becomes
`--fixture.default.node.binary mynode/oasis-node`.
5 changes: 5 additions & 0 deletions .changelog/2848.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
`oasis-net-runner`: Add support for fixtures in JSON file

New flag `--fixture.file` allows user to load default fixture from JSON file.
In addition `dump-fixture` command dumps configured JSON-encoded fixture to
standard output which can serve as a template.
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ runtime, do:

```
./go/oasis-net-runner/oasis-net-runner \
--net.node.binary go/oasis-node/oasis-node \
--net.runtime.binary target/default/debug/simple-keyvalue \
--net.runtime.loader target/default/debug/oasis-core-runtime-loader \
--net.keymanager.binary target/default/debug/simple-keymanager
--fixture.default.node.binary go/oasis-node/oasis-node \
--fixture.default.runtime.binary target/default/debug/simple-keyvalue \
--fixture.default.runtime.loader target/default/debug/oasis-core-runtime-loader \
--fixture.default.keymanager.binary target/default/debug/simple-keymanager
```

Wait for the network to start, there should be messages about nodes being
Expand Down Expand Up @@ -321,7 +321,6 @@ slightly different environmental variables set:
export OASIS_UNSAFE_SKIP_AVR_VERIFY="1"
export OASIS_UNSAFE_KM_POLICY_KEYS="1"
export OASIS_UNSAFE_ALLOW_DEBUG_ENCLAVES="1"
export OASIS_TEE_HARDWARE=intel-sgx
make
```

Expand Down Expand Up @@ -360,10 +359,11 @@ except the `oasis-net-runner` invocation:
<!-- markdownlint-disable line-length -->
```
./go/oasis-net-runner/oasis-net-runner \
--net.node.binary go/oasis-node/oasis-node \
--net.runtime.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keyvalue.sgxs \
--net.runtime.loader target/default/debug/oasis-core-runtime-loader \
--net.keymanager.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keymanager.sgxs
--fixture.default.tee_hardware intel-sgx \
--fixture.default.node.binary go/oasis-node/oasis-node \
--fixture.default.runtime.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keyvalue.sgxs \
--fixture.default.runtime.loader target/default/debug/oasis-core-runtime-loader \
--fixture.default.keymanager.binary target/sgx/x86_64-fortanix-unknown-sgx/debug/simple-keymanager.sgxs
```
<!-- markdownlint-enable line-length -->

Expand All @@ -389,8 +389,12 @@ To run all tests:
make test
```

Do not forget to set `OASIS_TEE_HARDWARE` flag (see above), if you want to
execute tests under SGX.
To execute tests using SGX set the following environmental variable before
running the tests:

```
export OASIS_TEE_HARDWARE=intel-sgx
```

### Troubleshooting

Expand Down
31 changes: 27 additions & 4 deletions go/oasis-net-runner/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package cmd implements the commands for the net-runner executable.
// Package cmd implements commands for oasis-net-runner executable.
package cmd

import (
Expand Down Expand Up @@ -34,6 +34,12 @@ var (
RunE: runRoot,
}

dumpFixtureCmd = &cobra.Command{
Use: "dump-fixture",
Short: "dump configured fixture to standard output",
Run: doDumpFixture,
}

rootFlags = flag.NewFlagSet("", flag.ContinueOnError)

cfgFile string
Expand Down Expand Up @@ -118,8 +124,7 @@ func runRoot(cmd *cobra.Command, args []string) error {
return fmt.Errorf("root: failed to setup child environment: %w", err)
}

// TODO: Support loading network fixtures from JSON files.
fixture, err := fixtures.NewDefaultFixture()
fixture, err := fixtures.GetFixture()
if err != nil {
return err
}
Expand Down Expand Up @@ -161,6 +166,20 @@ func runRoot(cmd *cobra.Command, args []string) error {
return nil
}

func doDumpFixture(cmd *cobra.Command, args []string) {
f, err := fixtures.GetFixture()
if err != nil {
common.EarlyLogAndExit(err)
}

// Encode fixture as JSON and dump it to stdout.
data, err := fixtures.DumpFixture(f)
if err != nil {
common.EarlyLogAndExit(fmt.Errorf("doDumpFixture: failed to marshal fixture: %w", err))
}
fmt.Printf("%s", data)
}

func init() {
logFmt := logging.FmtLogfmt
logLevel := logging.LevelInfo
Expand All @@ -173,7 +192,11 @@ func init() {

rootCmd.PersistentFlags().AddFlagSet(rootFlags)
rootCmd.PersistentFlags().AddFlagSet(env.Flags)
rootCmd.Flags().AddFlagSet(fixtures.Flags)
rootCmd.Flags().AddFlagSet(fixtures.DefaultFixtureFlags)
rootCmd.Flags().AddFlagSet(fixtures.FileFixtureFlags)

dumpFixtureCmd.Flags().AddFlagSet(fixtures.DefaultFixtureFlags)
rootCmd.AddCommand(dumpFixtureCmd)

cobra.OnInitialize(func() {
if cfgFile != "" {
Expand Down
43 changes: 19 additions & 24 deletions go/oasis-net-runner/fixtures/default.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Package fixtures provides network configuration fixtures.
package fixtures

import (
"math"
"time"

flag "github.com/spf13/pflag"
"github.com/spf13/viper"

"github.com/oasislabs/oasis-core/go/common"
Expand All @@ -17,26 +15,23 @@ import (
)

const (
cfgNodeBinary = "net.node.binary"
cfgRuntimeBinary = "net.runtime.binary"
cfgRuntimeGenesisState = "net.runtime.genesis_state"
cfgRuntimeLoader = "net.runtime.loader"
cfgKeymanagerBinary = "net.keymanager.binary"
cfgTEEHardware = "net.tee_hardware"
cfgEpochtimeMock = "net.epochtime_mock"
cfgHaltEpoch = "net.halt_epoch"
cfgEpochtimeMock = "fixture.default.epochtime_mock"
cfgHaltEpoch = "fixture.default.halt_epoch"
cfgKeymanagerBinary = "fixture.default.keymanager.binary"
cfgNodeBinary = "fixture.default.node.binary"
cfgRuntimeBinary = "fixture.default.runtime.binary"
cfgRuntimeGenesisState = "fixture.default.runtime.genesis_state"
cfgRuntimeLoader = "fixture.default.runtime.loader"
cfgTEEHardware = "fixture.default.tee_hardware"
)

var (
// Flags is the command line flags for the fixtures.
Flags = flag.NewFlagSet("", flag.ContinueOnError)

runtimeID common.Namespace
keymanagerID common.Namespace
)

// NewDefaultFixture returns a default network fixture.
func NewDefaultFixture() (*oasis.NetworkFixture, error) {
// newDefaultFixture returns a default network fixture.
func newDefaultFixture() (*oasis.NetworkFixture, error) {
var tee node.TEEHardware
err := tee.FromString(viper.GetString(cfgTEEHardware))
if err != nil {
Expand Down Expand Up @@ -134,15 +129,15 @@ func NewDefaultFixture() (*oasis.NetworkFixture, error) {
}

func init() {
Flags.String(cfgNodeBinary, "oasis-node", "path to the oasis-node binary")
Flags.String(cfgRuntimeBinary, "simple-keyvalue", "path to the runtime binary")
Flags.String(cfgRuntimeGenesisState, "", "path to the runtime genesis state")
Flags.String(cfgRuntimeLoader, "oasis-core-runtime-loader", "path to the runtime loader")
Flags.String(cfgKeymanagerBinary, "simple-keymanager", "path to the keymanager runtime")
Flags.String(cfgTEEHardware, "", "TEE hardware to use")
Flags.Bool(cfgEpochtimeMock, false, "use mock epochtime")
Flags.Uint64(cfgHaltEpoch, math.MaxUint64, "halt epoch height")
_ = viper.BindPFlags(Flags)
DefaultFixtureFlags.Bool(cfgEpochtimeMock, false, "use mock epochtime")
DefaultFixtureFlags.Uint64(cfgHaltEpoch, math.MaxUint64, "halt epoch height")
DefaultFixtureFlags.String(cfgKeymanagerBinary, "simple-keymanager", "path to the keymanager runtime")
DefaultFixtureFlags.String(cfgNodeBinary, "oasis-node", "path to the oasis-node binary")
DefaultFixtureFlags.String(cfgRuntimeBinary, "simple-keyvalue", "path to the runtime binary")
DefaultFixtureFlags.String(cfgRuntimeGenesisState, "", "path to the runtime genesis state")
DefaultFixtureFlags.String(cfgRuntimeLoader, "oasis-core-runtime-loader", "path to the runtime loader")
DefaultFixtureFlags.String(cfgTEEHardware, "", "TEE hardware to use")
_ = viper.BindPFlags(DefaultFixtureFlags)

_ = runtimeID.UnmarshalHex("8000000000000000000000000000000000000000000000000000000000000000")
_ = keymanagerID.UnmarshalHex("c000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff")
Expand Down
34 changes: 34 additions & 0 deletions go/oasis-net-runner/fixtures/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package fixtures

import (
"encoding/json"
"fmt"
"io/ioutil"

"github.com/spf13/viper"

"github.com/oasislabs/oasis-core/go/oasis-test-runner/oasis"
)

const (
cfgFile = "fixture.file"
)

// newFixtureFromFile parses given JSON file and creates new fixture object from it.
func newFixtureFromFile(path string) (*oasis.NetworkFixture, error) {
f := oasis.NetworkFixture{}
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("newFixtureFromFile: failed to open fixture file: %w", err)
}
if err = json.Unmarshal(data, &f); err != nil {
return nil, fmt.Errorf("newFixtureFromFile: failed to unmarshal JSON from fixture file: %w", err)
}

return &f, nil
}

func init() {
FileFixtureFlags.String(cfgFile, "", "path to JSON-encoded fixture input file")
_ = viper.BindPFlags(FileFixtureFlags)
}
43 changes: 43 additions & 0 deletions go/oasis-net-runner/fixtures/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Package fixtures provides network configuration fixtures.
package fixtures

import (
"encoding/json"

flag "github.com/spf13/pflag"
"github.com/spf13/viper"

"github.com/oasislabs/oasis-core/go/oasis-test-runner/oasis"
)

var (
// FileFixtureFlags are command line flags for the fixtures.
FileFixtureFlags = flag.NewFlagSet("", flag.ContinueOnError)

// DefaultFixtureFlags are command line flags for the fixture.default.* flags.
DefaultFixtureFlags = flag.NewFlagSet("", flag.ContinueOnError)
)

// GetFixture generates fixture object from given file or default fixture, if no fixtures file provided.
func GetFixture() (f *oasis.NetworkFixture, err error) {
if viper.IsSet(cfgFile) {
f, err = newFixtureFromFile(viper.GetString(cfgFile))
} else {
f, err = newDefaultFixture()
}
if err != nil {
return
}

return
}

// DumpFixture dumps given fixture to JSON-encoded bytes.
func DumpFixture(f *oasis.NetworkFixture) ([]byte, error) {
data, err := json.Marshal(f)
if err != nil {
return nil, err
}

return data, nil
}
46 changes: 46 additions & 0 deletions go/oasis-net-runner/fixtures/fixtures_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package fixtures

import (
"io/ioutil"
"testing"

"github.com/stretchr/testify/require"
)

const (
defaultFixturePath = "../../../tests/fixture-data/net-runner/default.json"
)

func TestDefaultFixture(t *testing.T) {
f, err := newDefaultFixture()
require.Nil(t, err)
require.NotNil(t, f)

data, err := DumpFixture(f)
require.Nil(t, err)
require.NotNil(t, data)

storedData, err := ioutil.ReadFile(defaultFixturePath)
require.Nil(t, err)
require.NotNil(t, storedData)

require.EqualValues(t, storedData, data)
}

func TestCustomFixture(t *testing.T) {
f, _ := newDefaultFixture()
f.Network.NodeBinary = "myNodeBinary"
f.Network.ConsensusBackend = "myConsensusBackend"
f.Network.ConsensusGasCostsTxByte = 123456789

data, err := DumpFixture(f)
require.Nil(t, err)
tmpFile, _ := ioutil.TempFile("", "oasis-net-runner-customfixture.*.json")
path := tmpFile.Name()
_, _ = tmpFile.Write(data)
tmpFile.Close()

fs, err := newFixtureFromFile(path)
require.Nil(t, err)
require.EqualValues(t, f, fs)
}
1 change: 1 addition & 0 deletions tests/fixture-data/net-runner/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"tee":{"hardware":0,"mr_signer":null},"network":{"node_binary":"oasis-node","runtime_loader_binary":"oasis-core-runtime-loader","consensus_backend":"","consensus_timeout_commit":1000000000,"consensus_gas_costs_tx_byte":0,"halt_epoch":18446744073709551615,"epochtime_mock":false,"epochtime_tendermint_interval":0,"deterministic_identities":false,"staking_genesis":""},"entities":[{"IsDebugTestEntity":true,"Restore":false},{"IsDebugTestEntity":false,"Restore":false}],"runtimes":[{"id":"wAAAAAAAAAD///////////////////////////////8=","kind":2,"entity":0,"keymanager":-1,"binary":"simple-keymanager","genesis_state":"","genesis_round":0,"executor":{"group_size":0,"group_backup_size":0,"allowed_stragglers":0,"round_timeout":0},"merge":{"group_size":0,"group_backup_size":0,"allowed_stragglers":0,"round_timeout":0},"txn_scheduler":{"group_size":0,"algorithm":"","batch_flush_timeout":0,"max_batch_size":0,"max_batch_size_bytes":0},"storage":{"group_size":0,"max_apply_write_log_entries":0,"max_apply_ops":0,"max_merge_roots":0,"max_merge_ops":0,"checkpoint_interval":0,"checkpoint_num_kept":0,"checkpoint_chunk_size":0},"admission_policy":{"any_node":{}},"pruner":{"strategy":"","interval":0,"num_kept":0}},{"id":"gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","kind":1,"entity":0,"keymanager":0,"binary":"simple-keyvalue","genesis_state":"","genesis_round":0,"executor":{"group_size":2,"group_backup_size":1,"allowed_stragglers":0,"round_timeout":20000000000},"merge":{"group_size":2,"group_backup_size":1,"allowed_stragglers":0,"round_timeout":20000000000},"txn_scheduler":{"group_size":2,"algorithm":"batching","batch_flush_timeout":20000000000,"max_batch_size":1,"max_batch_size_bytes":16777216},"storage":{"group_size":1,"max_apply_write_log_entries":100000,"max_apply_ops":2,"max_merge_roots":8,"max_merge_ops":2,"checkpoint_interval":0,"checkpoint_num_kept":0,"checkpoint_chunk_size":0},"admission_policy":{"any_node":{}},"pruner":{"strategy":"","interval":0,"num_kept":0}}],"validators":[{"allow_early_termination":false,"allow_error_termination":false,"entity":1,"min_gas_price":0,"submission_gas_price":0,"tendermint_recover_corrupted_wal":false}],"keymanagers":[{"runtime":0,"entity":1,"allow_early_termination":false,"allow_error_termination":false,"submission_gas_price":0}],"storage_workers":[{"backend":"badger","entity":1,"allow_early_termination":false,"allow_error_termination":false,"submission_gas_price":0}],"compute_workers":[{"entity":1,"runtime_backend":"","allow_early_termination":false,"allow_error_termination":false,"submission_gas_price":0},{"entity":1,"runtime_backend":"","allow_early_termination":false,"allow_error_termination":false,"submission_gas_price":0},{"entity":1,"runtime_backend":"","allow_early_termination":false,"allow_error_termination":false,"submission_gas_price":0}],"clients":[{"consensus_disable_check_tx":false}]}

0 comments on commit e9945c8

Please sign in to comment.