Skip to content

Commit de9ebe8

Browse files
authoredJul 28, 2020
Merge pull request #229 from CosmWasm/add-gaiaflex
Add gaiaflex to Makefile and Dockerfile
2 parents 23d1fd8 + f3cf373 commit de9ebe8

17 files changed

+222
-915
lines changed
 

‎Dockerfile

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
FROM cosmwasm/go-ext-builder:0.8.2-alpine AS rust-builder
44

55
RUN apk add git
6-
# without this, build with LEDGER_ENABLED=false
7-
RUN apk add libusb-dev linux-headers
86

97
# copy all code into /code
108
WORKDIR /code
@@ -34,19 +32,21 @@ COPY --from=rust-builder /lib/libgo_cosmwasm_muslc.a /lib/libgo_cosmwasm_muslc.a
3432

3533
# force it to use static lib (from above) not standard libgo_cosmwasm.so file
3634
RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build
37-
# we also (temporarily) build the testnet binaries here
35+
# we also (temporarily?) build the testnet binaries here
3836
RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build-coral
37+
RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build-gaiaflex
3938

4039
# --------------------------------------------------------
4140
FROM alpine:3.12
4241

4342
COPY --from=go-builder /code/build/wasmd /usr/bin/wasmd
44-
COPY --from=go-builder /code/build/wasmgovd /usr/bin/wasmgovd
4543
COPY --from=go-builder /code/build/wasmcli /usr/bin/wasmcli
4644

4745
# testnet
4846
COPY --from=go-builder /code/build/coral /usr/bin/coral
4947
COPY --from=go-builder /code/build/corald /usr/bin/corald
48+
COPY --from=go-builder /code/build/gaiaflex /usr/bin/gaiaflex
49+
COPY --from=go-builder /code/build/gaiaflexd /usr/bin/gaiaflexd
5050

5151
COPY docker/* /opt/
5252
RUN chmod +x /opt/*.sh

‎Makefile

+28-3
Original file line numberDiff line numberDiff line change
@@ -69,34 +69,59 @@ coral_ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=coral \
6969
-X github.com/CosmWasm/wasmd/app.NodeDir=.corald \
7070
-X github.com/CosmWasm/wasmd/app.Bech32Prefix=coral \
7171
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)"
72+
# we could consider enabling governance override?
73+
# -X github.com/CosmWasm/wasmd/app.EnableSpecificProposals=MigrateContract,UpdateAdmin,ClearAdmin \
7274
7375
coral_ldflags += $(LDFLAGS)
7476
coral_ldflags := $(strip $(coral_ldflags))
7577

78+
flex_ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=gaiaflex \
79+
-X github.com/cosmos/cosmos-sdk/version.ServerName=gaiaflexd \
80+
-X github.com/cosmos/cosmos-sdk/version.ClientName=gaiaflex \
81+
-X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \
82+
-X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \
83+
-X github.com/CosmWasm/wasmd/app.ProposalsEnabled=true \
84+
-X github.com/CosmWasm/wasmd/app.CLIDir=.gaiaflex \
85+
-X github.com/CosmWasm/wasmd/app.NodeDir=.gaiaflexd \
86+
-X github.com/CosmWasm/wasmd/app.Bech32Prefix=cosmos \
87+
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)"
88+
89+
flex_ldflags += $(LDFLAGS)
90+
flex_ldflags := $(strip $(flex_ldflags))
91+
7692
BUILD_FLAGS := -tags $(build_tags_comma_sep) -ldflags '$(ldflags)' -trimpath
7793
CORAL_BUILD_FLAGS := -tags $(build_tags_comma_sep) -ldflags '$(coral_ldflags)' -trimpath
94+
FLEX_BUILD_FLAGS := -tags $(build_tags_comma_sep) -ldflags '$(flex_ldflags)' -trimpath
7895

7996
all: install lint test
8097

8198
build: go.sum
8299
ifeq ($(OS),Windows_NT)
83-
# wasmd nodes not supported on windows, maybe the cli?
100+
# wasmd nodes not supported on windows, maybe the cli?
84101
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmcli.exe ./cmd/wasmcli
85102
else
86103
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmd ./cmd/wasmd
87-
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmgovd ./cmd/wasmgovd
88104
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmcli ./cmd/wasmcli
89105
endif
90106

91107
build-coral: go.sum
92108
ifeq ($(OS),Windows_NT)
93-
# wasmd nodes not supported on windows, maybe the cli?
109+
# wasmd nodes not supported on windows, maybe the cli?
94110
go build -mod=readonly $(CORAL_BUILD_FLAGS) -o build/coral.exe ./cmd/wasmcli
95111
else
96112
go build -mod=readonly $(CORAL_BUILD_FLAGS) -o build/corald ./cmd/wasmd
97113
go build -mod=readonly $(CORAL_BUILD_FLAGS) -o build/coral ./cmd/wasmcli
98114
endif
99115

116+
build-gaiaflex: go.sum
117+
ifeq ($(OS),Windows_NT)
118+
# wasmd nodes not supported on windows, maybe the cli?
119+
go build -mod=readonly $(FLEX_BUILD_FLAGS) -o build/gaiaflex.exe ./cmd/wasmcli
120+
else
121+
go build -mod=readonly $(FLEX_BUILD_FLAGS) -o build/gaiaflexd ./cmd/wasmd
122+
go build -mod=readonly $(FLEX_BUILD_FLAGS) -o build/gaiaflex ./cmd/wasmcli
123+
endif
124+
100125
build-linux: go.sum
101126
LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build
102127

‎README.md

+31
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,37 @@ docker run --rm -it \
129129
cosmwasm/wasmd:latest ./logs.sh
130130
```
131131

132+
## Runtime flags
133+
134+
We provide a number of variables in `app/app.go` that are intended to be set via `-ldflags -X ...`
135+
compile-time flags. This enables us to avoid copying a new binary directory over for each small change
136+
to the configuration.
137+
138+
Available flags:
139+
140+
* `-X github.com/CosmWasm/wasmd/app.CLIDir=.coral` - set the config directory for the cli (default `~/.wasmcli`)
141+
* `-X github.com/CosmWasm/wasmd/app.NodeDir=.corald` - set the config/data directory for the node (default `~/.wasmd`)
142+
* `-X github.com/CosmWasm/wasmd/app.Bech32Prefix=coral` - set the bech32 prefix for all accounts (default `cosmos`)
143+
* `-X github.com/CosmWasm/wasmd/app.ProposalsEnabled=true` - enable all x/wasm governance proposals (default `false`)
144+
* `-X github.com/CosmWasm/wasmd/app.EnableSpecificProposals=MigrateContract,UpdateAdmin,ClearAdmin` -
145+
enable a subset of the x/wasm governance proposal types (overrides `ProposalsEnabled`)
146+
147+
Examples:
148+
149+
* [`wasmd`](./Makefile#L50-L55) is a generic, permissionless version using the `cosmos` bech32 prefix
150+
* [`gaiaflex`](./Makefile#L78-L87) is a generic, *permissioned* version using the `cosmos` bech32 prefix
151+
* [`coral`](./Makefile#L63-L71) is a permissionless version designed for a specific testnet, with a `coral` bech32 prefix
152+
153+
## Genesis Configuration
154+
155+
@alpe we should document all the genesis config for x/wasm even more.
156+
157+
Tip: if you want to lock this down to a permisisoned network, the following script can edit the genesis file
158+
to only allow permissioned use of code upload or instantiating. (Make sure you set `app.ProposalsEnabled=true`
159+
in this binary):
160+
161+
`sed -i 's/permission": "Everybody"/permission": "Nobody"/' .../config/genesis.json`
162+
132163
## Contributors
133164

134165
Much thanks to all who have contributed to this project, from this app, to the `cosmwasm` framework, to example contracts and documentation.

‎app/app.go

+26
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"io"
55
"os"
66
"path/filepath"
7+
"strings"
78

89
"github.com/CosmWasm/wasmd/x/wasm"
910
wasmclient "github.com/CosmWasm/wasmd/x/wasm/client"
@@ -44,8 +45,33 @@ var (
4445
CLIDir = ".wasmcli"
4546
NodeDir = ".wasmd"
4647
Bech32Prefix = sdk.Bech32MainPrefix
48+
49+
// If EnabledSpecificProposals is "", and this is "true", then enable all x/wasm proposals.
50+
// If EnabledSpecificProposals is "", and this is not "true", then disable all x/wasm proposals.
51+
ProposalsEnabled = "false"
52+
// If set to non-empty string it must be comma-separated list of values that are all a subset
53+
// of "EnableAllProposals" (takes precedence over ProposalsEnabled)
54+
// https://github.com/CosmWasm/wasmd/blob/02a54d33ff2c064f3539ae12d75d027d9c665f05/x/wasm/internal/types/proposal.go#L28-L34
55+
EnableSpecificProposals = ""
4756
)
4857

58+
// GetEnabledProposals parses the ProposalsEnabled / EnableSpecificProposals values to
59+
// produce a list of enabled proposals to pass into wasmd app.
60+
func GetEnabledProposals() []wasm.ProposalType {
61+
if EnableSpecificProposals == "" {
62+
if ProposalsEnabled == "true" {
63+
return wasm.EnableAllProposals
64+
}
65+
return wasm.DisableAllProposals
66+
}
67+
chunks := strings.Split(EnableSpecificProposals, ",")
68+
proposals, err := wasm.ConvertToProposals(chunks)
69+
if err != nil {
70+
panic(err)
71+
}
72+
return proposals
73+
}
74+
4975
// These constants are derived from the above variables.
5076
// These are the ones we will want to use in the code, based on
5177
// any overrides above

‎app/app_test.go

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
package app
22

33
import (
4+
"github.com/magiconair/properties/assert"
45
"os"
56
"testing"
67

7-
"github.com/CosmWasm/wasmd/x/wasm"
88
"github.com/stretchr/testify/require"
99
"github.com/tendermint/tendermint/libs/log"
10-
db "github.com/tendermint/tm-db"
1110

1211
"github.com/cosmos/cosmos-sdk/codec"
1312
"github.com/cosmos/cosmos-sdk/simapp"
14-
1513
abci "github.com/tendermint/tendermint/abci/types"
14+
db "github.com/tendermint/tm-db"
15+
16+
"github.com/CosmWasm/wasmd/x/wasm"
1617
)
1718

1819
func TestWasmdExport(t *testing.T) {
@@ -37,6 +38,37 @@ func TestBlackListedAddrs(t *testing.T) {
3738
}
3839
}
3940

41+
func TestGetEnabledProposals(t *testing.T) {
42+
cases := map[string]struct {
43+
proposalsEnabled string
44+
specificEnabled string
45+
expected []wasm.ProposalType
46+
}{
47+
"all disabled": {
48+
proposalsEnabled: "false",
49+
expected: wasm.DisableAllProposals,
50+
},
51+
"all enabled": {
52+
proposalsEnabled: "true",
53+
expected: wasm.EnableAllProposals,
54+
},
55+
"some enabled": {
56+
proposalsEnabled: "okay",
57+
specificEnabled: "StoreCode,InstantiateContract",
58+
expected: []wasm.ProposalType{wasm.ProposalTypeStoreCode, wasm.ProposalTypeInstantiateContract},
59+
},
60+
}
61+
62+
for name, tc := range cases {
63+
t.Run(name, func(t *testing.T) {
64+
ProposalsEnabled = tc.proposalsEnabled
65+
EnableSpecificProposals = tc.specificEnabled
66+
proposals := GetEnabledProposals()
67+
assert.Equal(t, tc.expected, proposals)
68+
})
69+
}
70+
}
71+
4072
func setGenesis(gapp *WasmApp) error {
4173
genesisState := simapp.NewDefaultGenesisState()
4274
genesisState[wasm.ModuleName] = wasm.AppModuleBasic{}.DefaultGenesis()

‎cmd/wasmd/main.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"io"
77

88
"github.com/CosmWasm/wasmd/app"
9-
"github.com/CosmWasm/wasmd/x/wasm"
109
"github.com/cosmos/cosmos-sdk/baseapp"
1110
"github.com/cosmos/cosmos-sdk/client/debug"
1211
"github.com/cosmos/cosmos-sdk/client/flags"
@@ -90,7 +89,8 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
9089
}
9190

9291
return app.NewWasmApp(logger, db, traceStore, true, invCheckPeriod,
93-
wasm.DisableAllProposals, skipUpgradeHeights,
92+
app.GetEnabledProposals(),
93+
skipUpgradeHeights,
9494
baseapp.SetPruning(pruningOpts),
9595
baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
9696
baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
@@ -103,14 +103,14 @@ func exportAppStateAndTMValidators(
103103
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
104104

105105
if height != -1 {
106-
gapp := app.NewWasmApp(logger, db, traceStore, false, uint(1), wasm.DisableAllProposals, nil)
106+
gapp := app.NewWasmApp(logger, db, traceStore, false, uint(1), app.GetEnabledProposals(), nil)
107107
err := gapp.LoadHeight(height)
108108
if err != nil {
109109
return nil, nil, err
110110
}
111111
return gapp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
112112
}
113113

114-
gapp := app.NewWasmApp(logger, db, traceStore, true, uint(1), wasm.DisableAllProposals, nil)
114+
gapp := app.NewWasmApp(logger, db, traceStore, true, uint(1), app.GetEnabledProposals(), nil)
115115
return gapp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
116116
}

‎cmd/wasmd/replay.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"time"
99

1010
"github.com/CosmWasm/wasmd/app"
11-
"github.com/CosmWasm/wasmd/x/wasm"
1211
"github.com/cosmos/cosmos-sdk/baseapp"
1312
"github.com/cosmos/cosmos-sdk/server"
1413
storetypes "github.com/cosmos/cosmos-sdk/store/types"
@@ -92,7 +91,7 @@ func replayTxs(rootDir string) error {
9291
fmt.Fprintln(os.Stderr, "Creating application")
9392
gapp := app.NewWasmApp(
9493
// TODO: do we want to set skipUpgradeHieghts here?
95-
ctx.Logger, appDB, traceStoreWriter, true, uint(1), wasm.DisableAllProposals, nil,
94+
ctx.Logger, appDB, traceStoreWriter, true, uint(1), app.GetEnabledProposals(), nil,
9695
baseapp.SetPruning(storetypes.PruneEverything))
9796

9897
// Genesis

‎cmd/wasmgovd/genaccounts.go

-153
This file was deleted.

‎cmd/wasmgovd/main.go

-117
This file was deleted.

‎cmd/wasmgovd/replay.go

-191
This file was deleted.

‎cmd/wasmgovd/testnet.go

-374
This file was deleted.

‎docker/run_wasmgovd.sh

-10
This file was deleted.

‎docker/setup_wasmgovd.sh

-24
This file was deleted.

‎go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/golang/mock v1.4.3 // indirect
99
github.com/google/gofuzz v1.0.0
1010
github.com/gorilla/mux v1.7.4
11+
github.com/magiconair/properties v1.8.1
1112
github.com/onsi/ginkgo v1.8.0 // indirect
1213
github.com/onsi/gomega v1.5.0 // indirect
1314
github.com/otiai10/copy v1.0.2

‎x/wasm/alias.go

+28-22
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,40 @@ import (
1111
)
1212

1313
const (
14-
DefaultParamspace = types.DefaultParamspace
15-
ModuleName = types.ModuleName
16-
StoreKey = types.StoreKey
17-
TStoreKey = types.TStoreKey
18-
QuerierRoute = types.QuerierRoute
19-
RouterKey = types.RouterKey
20-
MaxWasmSize = types.MaxWasmSize
21-
MaxLabelSize = types.MaxLabelSize
22-
BuildTagRegexp = types.BuildTagRegexp
23-
MaxBuildTagSize = types.MaxBuildTagSize
24-
CustomEventType = types.CustomEventType
25-
AttributeKeyContractAddr = types.AttributeKeyContractAddr
26-
GasMultiplier = keeper.GasMultiplier
27-
MaxGas = keeper.MaxGas
28-
QueryListContractByCode = keeper.QueryListContractByCode
29-
QueryGetContract = keeper.QueryGetContract
30-
QueryGetContractState = keeper.QueryGetContractState
31-
QueryGetCode = keeper.QueryGetCode
32-
QueryListCode = keeper.QueryListCode
33-
QueryMethodContractStateSmart = keeper.QueryMethodContractStateSmart
34-
QueryMethodContractStateAll = keeper.QueryMethodContractStateAll
35-
QueryMethodContractStateRaw = keeper.QueryMethodContractStateRaw
14+
DefaultParamspace = types.DefaultParamspace
15+
ModuleName = types.ModuleName
16+
StoreKey = types.StoreKey
17+
TStoreKey = types.TStoreKey
18+
QuerierRoute = types.QuerierRoute
19+
RouterKey = types.RouterKey
20+
MaxWasmSize = types.MaxWasmSize
21+
MaxLabelSize = types.MaxLabelSize
22+
BuildTagRegexp = types.BuildTagRegexp
23+
MaxBuildTagSize = types.MaxBuildTagSize
24+
CustomEventType = types.CustomEventType
25+
AttributeKeyContractAddr = types.AttributeKeyContractAddr
26+
ProposalTypeStoreCode = types.ProposalTypeStoreCode
27+
ProposalTypeInstantiateContract = types.ProposalTypeInstantiateContract
28+
ProposalTypeMigrateContract = types.ProposalTypeMigrateContract
29+
ProposalTypeUpdateAdmin = types.ProposalTypeUpdateAdmin
30+
ProposalTypeClearAdmin = types.ProposalTypeClearAdmin
31+
GasMultiplier = keeper.GasMultiplier
32+
MaxGas = keeper.MaxGas
33+
QueryListContractByCode = keeper.QueryListContractByCode
34+
QueryGetContract = keeper.QueryGetContract
35+
QueryGetContractState = keeper.QueryGetContractState
36+
QueryGetCode = keeper.QueryGetCode
37+
QueryListCode = keeper.QueryListCode
38+
QueryMethodContractStateSmart = keeper.QueryMethodContractStateSmart
39+
QueryMethodContractStateAll = keeper.QueryMethodContractStateAll
40+
QueryMethodContractStateRaw = keeper.QueryMethodContractStateRaw
3641
)
3742

3843
var (
3944
// functions aliases
4045
RegisterCodec = types.RegisterCodec
4146
ValidateGenesis = types.ValidateGenesis
47+
ConvertToProposals = types.ConvertToProposals
4248
GetCodeKey = types.GetCodeKey
4349
GetContractAddressKey = types.GetContractAddressKey
4450
GetContractStorePrefixKey = types.GetContractStorePrefixKey

‎x/wasm/internal/types/proposal.go

+26-8
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import (
1414
type ProposalType string
1515

1616
const (
17-
ProposalTypeStoreCode ProposalType = "StoreCode"
18-
ProposalTypeStoreInstantiateContract ProposalType = "InstantiateContract"
19-
ProposalTypeMigrateContract ProposalType = "MigrateContract"
20-
ProposalTypeUpdateAdmin ProposalType = "UpdateAdmin"
21-
ProposalTypeClearAdmin ProposalType = "ClearAdmin"
17+
ProposalTypeStoreCode ProposalType = "StoreCode"
18+
ProposalTypeInstantiateContract ProposalType = "InstantiateContract"
19+
ProposalTypeMigrateContract ProposalType = "MigrateContract"
20+
ProposalTypeUpdateAdmin ProposalType = "UpdateAdmin"
21+
ProposalTypeClearAdmin ProposalType = "ClearAdmin"
2222
)
2323

2424
// DisableAllProposals contains no wasm gov types.
@@ -27,15 +27,33 @@ var DisableAllProposals []ProposalType
2727
// EnableAllProposals contains all wasm gov types as keys.
2828
var EnableAllProposals = []ProposalType{
2929
ProposalTypeStoreCode,
30-
ProposalTypeStoreInstantiateContract,
30+
ProposalTypeInstantiateContract,
3131
ProposalTypeMigrateContract,
3232
ProposalTypeUpdateAdmin,
3333
ProposalTypeClearAdmin,
3434
}
3535

36+
// ConvertToProposals maps each key to a ProposalType and returns a typed list.
37+
// If any string is not a valid type (in this file), then return an error
38+
func ConvertToProposals(keys []string) ([]ProposalType, error) {
39+
valid := make(map[string]bool, len(EnableAllProposals))
40+
for _, key := range EnableAllProposals {
41+
valid[string(key)] = true
42+
}
43+
44+
proposals := make([]ProposalType, len(keys))
45+
for i, key := range keys {
46+
if _, ok := valid[key]; !ok {
47+
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "'%s' is not a valid ProposalType", key)
48+
}
49+
proposals[i] = ProposalType(key)
50+
}
51+
return proposals, nil
52+
}
53+
3654
func init() { // register new content types with the sdk
3755
govtypes.RegisterProposalType(string(ProposalTypeStoreCode))
38-
govtypes.RegisterProposalType(string(ProposalTypeStoreInstantiateContract))
56+
govtypes.RegisterProposalType(string(ProposalTypeInstantiateContract))
3957
govtypes.RegisterProposalType(string(ProposalTypeMigrateContract))
4058
govtypes.RegisterProposalType(string(ProposalTypeUpdateAdmin))
4159
govtypes.RegisterProposalType(string(ProposalTypeClearAdmin))
@@ -175,7 +193,7 @@ type InstantiateContractProposal struct {
175193

176194
// ProposalType returns the type
177195
func (p InstantiateContractProposal) ProposalType() string {
178-
return string(ProposalTypeStoreInstantiateContract)
196+
return string(ProposalTypeInstantiateContract)
179197
}
180198

181199
// ValidateBasic validates the proposal

‎x/wasm/internal/types/proposal_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,41 @@ contract: cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5
616616
})
617617
}
618618
}
619+
620+
func TestConvertToProposals(t *testing.T) {
621+
cases := map[string]struct {
622+
input string
623+
isError bool
624+
proposals []ProposalType
625+
}{
626+
"one proper item": {
627+
input: "UpdateAdmin",
628+
proposals: []ProposalType{ProposalTypeUpdateAdmin},
629+
},
630+
"multiple proper items": {
631+
input: "StoreCode,InstantiateContract,MigrateContract",
632+
proposals: []ProposalType{ProposalTypeStoreCode, ProposalTypeInstantiateContract, ProposalTypeMigrateContract},
633+
},
634+
"empty trailing item": {
635+
input: "StoreCode,",
636+
isError: true,
637+
},
638+
"invalid item": {
639+
input: "StoreCode,InvalidProposalType",
640+
isError: true,
641+
},
642+
}
643+
644+
for name, tc := range cases {
645+
t.Run(name, func(t *testing.T) {
646+
chunks := strings.Split(tc.input, ",")
647+
proposals, err := ConvertToProposals(chunks)
648+
if tc.isError {
649+
require.Error(t, err)
650+
} else {
651+
require.NoError(t, err)
652+
require.Equal(t, proposals, tc.proposals)
653+
}
654+
})
655+
}
656+
}

0 commit comments

Comments
 (0)
Please sign in to comment.