Skip to content

Commit

Permalink
Merge pull request #3800 from oasisprotocol/tjanez/pprinters
Browse files Browse the repository at this point in the history
go: Add pretty-printers for governance and upgrade types
  • Loading branch information
tjanez authored Mar 18, 2021
2 parents aed18a3 + 67b1c51 commit 1e16eed
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 0 deletions.
1 change: 1 addition & 0 deletions .changelog/3800.feature.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/common/version: Implement `PrettyPrint` interface for `ProtocolVersions`
4 changes: 4 additions & 0 deletions .changelog/3800.feature.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/governance: Implement `PrettyPrint` interface for various types

Implement `PrettyPrinter` for `ProposalContent`, `UpgradeProposal`,
`CancelUpgradeProposal` and `ProposalVote` types.
1 change: 1 addition & 0 deletions .changelog/3800.feature.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/upgrade: Implement `PrettyPrint` interface for `Descriptor`
20 changes: 20 additions & 0 deletions go/common/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
package version

import (
"context"
"fmt"
"io"
"regexp"
"runtime"
"strconv"
"strings"

"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
)

// VersionUndefined represents an undefined version.
const VersionUndefined = "undefined"

var _ prettyprint.PrettyPrinter = (*ProtocolVersions)(nil)

// NOTE: This should be kept in sync with runtime/src/common/version.rs.

// Version is a protocol version.
Expand Down Expand Up @@ -128,6 +134,20 @@ func (pv ProtocolVersions) String() string {
)
}

// PrettyPrint writes a pretty-printed representation of ProtocolVersions to the
// given writer.
func (pv ProtocolVersions) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sConsensus Protocol: %s\n", prefix, pv.ConsensusProtocol)
fmt.Fprintf(w, "%sRuntime Host Protocol: %s\n", prefix, pv.RuntimeHostProtocol)
fmt.Fprintf(w, "%sRuntime Committee Protocol: %s\n", prefix, pv.RuntimeCommitteeProtocol)
}

// PrettyType returns a representation of ProtocolVersions that can be used for
// pretty printing.
func (pv ProtocolVersions) PrettyType() (interface{}, error) {
return pv, nil
}

// Versions are current protocol versions.
var Versions = ProtocolVersions{
RuntimeHostProtocol,
Expand Down
69 changes: 69 additions & 0 deletions go/governance/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ package api
import (
"context"
"fmt"
"io"

beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common/crypto/hash"
"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/pubsub"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
Expand All @@ -18,6 +20,10 @@ import (
// ModuleName is a unique module name for the governance backend.
const ModuleName = "governance"

// ProposalContentInvalidText is the textual representation of an invalid
// ProposalContent.
const ProposalContentInvalidText = "(invalid)"

var (
// ErrInvalidArgument is the error returned on malformed argument(s).
ErrInvalidArgument = errors.New(ModuleName, 1, "governance: invalid argument")
Expand All @@ -44,6 +50,11 @@ var (
MethodSubmitProposal,
MethodCastVote,
}

_ prettyprint.PrettyPrinter = (*ProposalContent)(nil)
_ prettyprint.PrettyPrinter = (*UpgradeProposal)(nil)
_ prettyprint.PrettyPrinter = (*CancelUpgradeProposal)(nil)
_ prettyprint.PrettyPrinter = (*ProposalVote)(nil)
)

// ProposalContent is a consensus layer governance proposal content.
Expand Down Expand Up @@ -82,17 +93,62 @@ func (p *ProposalContent) Equals(other *ProposalContent) bool {
}
}

// PrettyPrint writes a pretty-printed representation of ProposalContent to the
// given writer.
func (p ProposalContent) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
switch {
case p.Upgrade != nil && p.CancelUpgrade == nil:
fmt.Fprintf(w, "%sUpgrade:\n", prefix)
p.Upgrade.PrettyPrint(ctx, prefix+" ", w)
case p.CancelUpgrade != nil && p.Upgrade == nil:
fmt.Fprintf(w, "%sCancel Upgrade:\n", prefix)
p.CancelUpgrade.PrettyPrint(ctx, prefix+" ", w)
default:
fmt.Fprintf(w, "%s%s\n", prefix, ProposalContentInvalidText)
}
}

// PrettyType returns a representation of ProposalContent that can be used for
// pretty printing.
func (p ProposalContent) PrettyType() (interface{}, error) {
return p, nil
}

// UpgradeProposal is an upgrade proposal.
type UpgradeProposal struct {
upgrade.Descriptor
}

// PrettyPrint writes a pretty-printed representation of UpgradeProposal to the
// given writer.
func (u UpgradeProposal) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
u.Descriptor.PrettyPrint(ctx, prefix, w)
}

// PrettyType returns a representation of UpgradeProposal that can be used for
// pretty printing.
func (u UpgradeProposal) PrettyType() (interface{}, error) {
return u, nil
}

// CancelUpgradeProposal is an upgrade cancellation proposal.
type CancelUpgradeProposal struct {
// ProposalID is the identifier of the pending upgrade proposal.
ProposalID uint64 `json:"proposal_id"`
}

// PrettyPrint writes a pretty-printed representation of CancelUpgradeProposal
// to the given writer.
func (cu CancelUpgradeProposal) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sProposal ID: %d\n", prefix, cu.ProposalID)
}

// PrettyType returns a representation of CancelUpgradeProposal that can be used
// for pretty printing.
func (cu CancelUpgradeProposal) PrettyType() (interface{}, error) {
return cu, nil
}

// ProposalVote is a vote for a proposal.
type ProposalVote struct {
// ID is the unique identifier of a proposal.
Expand All @@ -101,6 +157,19 @@ type ProposalVote struct {
Vote Vote `json:"vote"`
}

// PrettyPrint writes a pretty-printed representation of ProposalVote to the
// given writer.
func (pv ProposalVote) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sProposal ID: %d\n", prefix, pv.ID)
fmt.Fprintf(w, "%sVote: %s\n", prefix, pv.Vote)
}

// PrettyType returns a representation of ProposalVote that can be used for
// pretty printing.
func (pv ProposalVote) PrettyType() (interface{}, error) {
return pv, nil
}

// Backend is a governance implementation.
type Backend interface {
// ActiveProposals returns a list of all proposals that have not yet closed.
Expand Down
43 changes: 43 additions & 0 deletions go/governance/api/api_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package api

import (
"bytes"
"context"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -139,3 +141,44 @@ func TestProposalContentEquals(t *testing.T) {
require.Equal(t, tc.equals, tc.p1.Equals(tc.p2), tc.msg)
}
}

func TestProposalContentPrettyPrint(t *testing.T) {
for _, tc := range []struct {
expRegex string
p *ProposalContent
}{
{
expRegex: "^Upgrade:",
p: &ProposalContent{
Upgrade: &UpgradeProposal{
Descriptor: api.Descriptor{Handler: "test"},
},
},
},
{
expRegex: "^Cancel Upgrade:",
p: &ProposalContent{
CancelUpgrade: &CancelUpgradeProposal{ProposalID: 42},
},
},
{
expRegex: ProposalContentInvalidText,
p: &ProposalContent{},
},
{
expRegex: ProposalContentInvalidText,
p: &ProposalContent{
Upgrade: &UpgradeProposal{
Descriptor: api.Descriptor{Handler: "test"},
},
CancelUpgrade: &CancelUpgradeProposal{ProposalID: 42},
},
},
} {
var actualPrettyPrint bytes.Buffer
tc.p.PrettyPrint(context.Background(), "", &actualPrettyPrint)
require.Regexp(t, tc.expRegex, actualPrettyPrint.String(),
"pretty printing proposal content didn't return the expected result",
)
}
}
19 changes: 19 additions & 0 deletions go/upgrade/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ package api
import (
"context"
"fmt"
"io"

beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/common/prettyprint"
"github.com/oasisprotocol/oasis-core/go/common/version"
)

Expand Down Expand Up @@ -63,6 +65,8 @@ var (

// ErrUpgradeInProgress is the error returned from CancelUpgrade when the upgrade being cancelled is already in progress.
ErrUpgradeInProgress = errors.New(ModuleName, 6, "upgrade: can not cancel upgrade in progress")

_ prettyprint.PrettyPrinter = (*Descriptor)(nil)
)

// Descriptor describes an upgrade.
Expand Down Expand Up @@ -127,6 +131,21 @@ func (d *Descriptor) EnsureCompatible() error {
return nil
}

// PrettyPrint writes a pretty-printed representation of Descriptor to the given
// writer.
func (d Descriptor) PrettyPrint(ctx context.Context, prefix string, w io.Writer) {
fmt.Fprintf(w, "%sHandler: %s\n", prefix, d.Handler)
fmt.Fprintf(w, "%sTarget Version:\n", prefix)
d.Target.PrettyPrint(ctx, prefix+" ", w)
fmt.Fprintf(w, "%sEpoch: %d\n", prefix, d.Epoch)
}

// PrettyType returns a representation of Descriptor that can be used for pretty
// printing.
func (d Descriptor) PrettyType() (interface{}, error) {
return d, nil
}

// PendingUpgrade describes a currently pending upgrade and includes the
// submitted upgrade descriptor.
type PendingUpgrade struct {
Expand Down

0 comments on commit 1e16eed

Please sign in to comment.