Skip to content

Commit

Permalink
CLI, "comid display" subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-fossati committed Oct 1, 2021
1 parent eabf7ed commit e872442
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 1 deletion.
111 changes: 111 additions & 0 deletions cli/cmd/comidDisplay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2021 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"errors"
"fmt"

"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/veraison/corim/comid"
)

var (
comidDisplayFiles []string
comidDisplayDirs []string
)

var comidDisplayCmd = NewComidDisplayCmd()

func NewComidDisplayCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "display",
Short: "display one or more CBOR-encoded CoMID(s) in human readable (JSON) format",
Long: `display one or more CBOR-encoded CoMID(s) in human readable (JSON) format",
Display CoMIDs in file c.cbor.
cli comid display --file=c.cbor
Display CoMIDs in files c1.cbor, c2.cbor and any cbor file in the comids/
directory.
cli comid display --file=c1.cbor --file=c2.cbor --dir=comids
`,

RunE: func(cmd *cobra.Command, args []string) error {
if err := checkComidDisplayArgs(); err != nil {
return err
}

filesList := filesList(comidDisplayFiles, comidDisplayDirs, ".cbor")
if len(filesList) == 0 {
return errors.New("no files found")
}

errs := 0
for _, file := range filesList {
if err := displayComid(file); err != nil {
fmt.Printf("failed displaying %q: %v", file, err)
errs++
continue
}
}

if errs != 0 {
return fmt.Errorf("%d/%d display(s) failed", errs, len(filesList))
}
return nil
},
}

cmd.Flags().StringArrayVarP(
&comidDisplayFiles, "file", "f", []string{}, "a CoMID file (in CBOR format)",
)

cmd.Flags().StringArrayVarP(
&comidDisplayDirs, "dir", "d", []string{}, "a directory containing CoMID files (in CBOR format)",
)

return cmd
}

func displayComid(file string) error {
var (
data []byte
err error
c comid.Comid
)

if data, err = afero.ReadFile(fs, file); err != nil {
return fmt.Errorf("error loading CoMID from %s: %w", file, err)
}

if err = c.FromCBOR(data); err != nil {
return fmt.Errorf("error decoding CoMID from %s: %w", file, err)
}

prettyPrint := true
json, err := c.ToJSON(prettyPrint)
if err != nil {
return fmt.Errorf("error JSON encoding CoMID %s: %w", file, err)
}

fmt.Println("[ ", file, " ]")
fmt.Println(string(json))

return nil
}

func checkComidDisplayArgs() error {
if len(comidDisplayFiles) == 0 && len(comidDisplayDirs) == 0 {
return errors.New("no files supplied")
}
return nil
}

func init() {
comidCmd.AddCommand(comidDisplayCmd)
}
119 changes: 119 additions & 0 deletions cli/cmd/comidDisplay_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright 2021 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

package cmd

import (
"fmt"
"testing"

"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_ComidDisplayCmd_unknown_argument(t *testing.T) {
cmd := NewComidDisplayCmd()

args := []string{"--unknown-argument=val"}
cmd.SetArgs(args)

err := cmd.Execute()
assert.EqualError(t, err, "unknown flag: --unknown-argument")
}

func Test_ComidDisplayCmd_no_files(t *testing.T) {
cmd := NewComidDisplayCmd()

// no args

err := cmd.Execute()
assert.EqualError(t, err, "no files supplied")
}

func Test_ComidDisplayCmd_no_files_found(t *testing.T) {
cmd := NewComidDisplayCmd()

args := []string{
"--file=unknown",
"--dir=unsure",
}
cmd.SetArgs(args)

err := cmd.Execute()
assert.EqualError(t, err, "no files found")
}

func Test_ComidDisplayCmd_file_with_invalid_cbor(t *testing.T) {
var err error

cmd := NewComidDisplayCmd()

fs = afero.NewMemMapFs()
err = afero.WriteFile(fs, "invalid.cbor", []byte{0xff, 0xff}, 0400)
require.NoError(t, err)

args := []string{
"--file=invalid.cbor",
}
cmd.SetArgs(args)

err = cmd.Execute()
assert.EqualError(t, err, "1/1 display(s) failed")
}

func Test_ComidDisplayCmd_file_with_invalid_comid(t *testing.T) {
var err error

cmd := NewComidDisplayCmd()

fs = afero.NewMemMapFs()
err = afero.WriteFile(fs, "bad-comid.cbor", []byte{0xa0}, 0400)
require.NoError(t, err)

args := []string{
"--file=bad-comid.cbor",
}
cmd.SetArgs(args)

err = cmd.Execute()
assert.EqualError(t, err, "1/1 display(s) failed")
}

func Test_ComidDisplayCmd_file_with_valid_comid(t *testing.T) {
var err error

cmd := NewComidDisplayCmd()

fs = afero.NewMemMapFs()
err = afero.WriteFile(fs, "ok.cbor", PSARefValCBOR, 0400)
require.NoError(t, err)

args := []string{
"--file=ok.cbor",
}
cmd.SetArgs(args)

fmt.Printf("%x\n", PSARefValCBOR)

err = cmd.Execute()
assert.NoError(t, err)
}

func Test_ComidDisplayCmd_file_with_valid_comid_from_dir(t *testing.T) {
var err error

cmd := NewComidDisplayCmd()

fs = afero.NewMemMapFs()
err = afero.WriteFile(fs, "testdir/ok.cbor", PSARefValCBOR, 0400)
require.NoError(t, err)

args := []string{
"--dir=testdir",
}
cmd.SetArgs(args)

err = cmd.Execute()
assert.NoError(t, err)
}
13 changes: 12 additions & 1 deletion comid/comid.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ func (o Comid) Valid() error {

// ToCBOR serializes the target Comid to CBOR
func (o Comid) ToCBOR() ([]byte, error) {
if err := o.Valid(); err != nil {
return nil, err
}

return em.Marshal(&o)
}

Expand All @@ -248,6 +252,13 @@ func (o *Comid) FromJSON(data []byte) error {
}

// ToJSON serializes the target Comid to JSON
func (o Comid) ToJSON() ([]byte, error) {
func (o Comid) ToJSON(prettyPrint bool) ([]byte, error) {
if err := o.Valid(); err != nil {
return nil, err
}

if prettyPrint {
return json.MarshalIndent(&o, "", " ")
}
return json.Marshal(&o)
}
4 changes: 4 additions & 0 deletions comid/measurement.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ func (o Mkey) MarshalCBOR() ([]byte, error) {
return em.Marshal(o.val)
}

func (o *Mkey) UnmarshalCBOR(data []byte) error {
return dm.Unmarshal(data, &o.val)
}

// Mval stores a measurement-values-map with JSON and CBOR serializations.
type Mval struct {
Ver *Version `cbor:"0,keyasint,omitempty" json:"version,omitempty"`
Expand Down

0 comments on commit e872442

Please sign in to comment.