diff options
Diffstat (limited to 'pkg/instance/request_test.go')
-rw-r--r-- | pkg/instance/request_test.go | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/pkg/instance/request_test.go b/pkg/instance/request_test.go new file mode 100644 index 0000000..0a5a908 --- /dev/null +++ b/pkg/instance/request_test.go @@ -0,0 +1,318 @@ +package stfe + +import ( + "bytes" + //"fmt" + "reflect" + "testing" + //"testing/iotest" + + "net/http" + + "github.com/system-transparency/stfe/pkg/testdata" + "github.com/system-transparency/stfe/pkg/types" +) + +func TestParseAddEntryV1Request(t *testing.T) { + lp := newLogParameters(t, nil) + for _, table := range []struct { + description string + breq *bytes.Buffer + wantErr bool + }{ + { + description: "invalid: nothing to unpack", + breq: bytes.NewBuffer(nil), + wantErr: true, + }, + { + description: "invalid: not a signed checksum entry", + breq: testdata.AddCosignatureBuffer(t, testdata.DefaultSth(t, testdata.Ed25519VkLog), &testdata.Ed25519SkWitness, &testdata.Ed25519VkWitness), + wantErr: true, + }, + { + description: "invalid: untrusted submitter", // only testdata.Ed25519VkSubmitter is registered by default in newLogParameters() + + breq: testdata.AddSignedChecksumBuffer(t, testdata.Ed25519SkSubmitter2, testdata.Ed25519VkSubmitter2), + wantErr: true, + }, + { + description: "invalid: signature does not cover message", + + breq: testdata.AddSignedChecksumBuffer(t, testdata.Ed25519SkSubmitter2, testdata.Ed25519VkSubmitter), + wantErr: true, + }, + { + description: "valid", + breq: testdata.AddSignedChecksumBuffer(t, testdata.Ed25519SkSubmitter, testdata.Ed25519VkSubmitter), + }, // TODO: add test case that disables submitter policy (i.e., unregistered namespaces are accepted) + } { + url := EndpointAddEntry.Path("http://example.com", lp.Prefix) + req, err := http.NewRequest("POST", url, table.breq) + if err != nil { + t.Fatalf("failed creating http request: %v", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + _, err = lp.parseAddEntryV1Request(req) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got errror %v but wanted %v in test %q: %v", got, want, table.description, err) + } + } +} + +func TestParseAddCosignatureV1Request(t *testing.T) { + lp := newLogParameters(t, nil) + for _, table := range []struct { + description string + breq *bytes.Buffer + wantErr bool + }{ + { + description: "invalid: nothing to unpack", + breq: bytes.NewBuffer(nil), + wantErr: true, + }, + { + description: "invalid: not a cosigned sth", + breq: testdata.AddSignedChecksumBuffer(t, testdata.Ed25519SkSubmitter, testdata.Ed25519VkSubmitter), + wantErr: true, + }, + { + description: "invalid: no cosignature", + breq: testdata.AddCosignatureBuffer(t, testdata.DefaultSth(t, testdata.Ed25519VkLog), &testdata.Ed25519SkWitness, nil), + wantErr: true, + }, + { + description: "invalid: untrusted witness", // only testdata.Ed25519VkWitness is registered by default in newLogParameters() + breq: testdata.AddCosignatureBuffer(t, testdata.DefaultSth(t, testdata.Ed25519VkLog), &testdata.Ed25519SkWitness2, &testdata.Ed25519VkWitness2), + wantErr: true, + }, + { + description: "invalid: signature does not cover message", + breq: testdata.AddCosignatureBuffer(t, testdata.DefaultSth(t, testdata.Ed25519VkLog), &testdata.Ed25519SkWitness2, &testdata.Ed25519VkWitness), + wantErr: true, + }, + { + description: "valid", + breq: testdata.AddCosignatureBuffer(t, testdata.DefaultSth(t, testdata.Ed25519VkLog), &testdata.Ed25519SkWitness, &testdata.Ed25519VkWitness), + }, // TODO: add test case that disables witness policy (i.e., unregistered namespaces are accepted) + } { + url := EndpointAddCosignature.Path("http://example.com", lp.Prefix) + req, err := http.NewRequest("POST", url, table.breq) + if err != nil { + t.Fatalf("failed creating http request: %v", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + _, err = lp.parseAddCosignatureV1Request(req) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got errror %v but wanted %v in test %q: %v", got, want, table.description, err) + } + } +} + +func TestNewGetConsistencyProofRequest(t *testing.T) { + lp := newLogParameters(t, nil) + for _, table := range []struct { + description string + req *types.GetConsistencyProofV1 + wantErr bool + }{ + { + description: "invalid: nothing to unpack", + req: nil, + wantErr: true, + }, + { + description: "invalid: first must be larger than zero", + req: &types.GetConsistencyProofV1{First: 0, Second: 0}, + wantErr: true, + }, + { + description: "invalid: second must be larger than first", + req: &types.GetConsistencyProofV1{First: 2, Second: 1}, + wantErr: true, + }, + { + description: "valid", + req: &types.GetConsistencyProofV1{First: 1, Second: 2}, + }, + } { + var buf *bytes.Buffer + if table.req == nil { + buf = bytes.NewBuffer(nil) + } else { + buf = bytes.NewBuffer(marshal(t, *table.req)) + } + + url := EndpointGetConsistencyProof.Path("http://example.com", lp.Prefix) + req, err := http.NewRequest("POST", url, buf) + if err != nil { + t.Fatalf("failed creating http request: %v", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + _, err = lp.parseGetConsistencyProofV1Request(req) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got errror %v but wanted %v in test %q: %v", got, want, table.description, err) + } + } +} + +func TestNewGetProofByHashRequest(t *testing.T) { + lp := newLogParameters(t, nil) + for _, table := range []struct { + description string + req *types.GetProofByHashV1 + wantErr bool + }{ + { + description: "invalid: nothing to unpack", + req: nil, + wantErr: true, + }, + { + description: "invalid: no entry in an empty tree", + req: &types.GetProofByHashV1{TreeSize: 0, Hash: testdata.LeafHash}, + wantErr: true, + }, + { + description: "valid", + req: &types.GetProofByHashV1{TreeSize: 1, Hash: testdata.LeafHash}, + }, + } { + var buf *bytes.Buffer + if table.req == nil { + buf = bytes.NewBuffer(nil) + } else { + buf = bytes.NewBuffer(marshal(t, *table.req)) + } + + url := EndpointGetProofByHash.Path("http://example.com", lp.Prefix) + req, err := http.NewRequest("POST", url, buf) + if err != nil { + t.Fatalf("failed creating http request: %v", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + _, err = lp.parseGetProofByHashV1Request(req) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got errror %v but wanted %v in test %q: %v", got, want, table.description, err) + } + } +} + +func TestParseGetEntriesV1Request(t *testing.T) { + lp := newLogParameters(t, nil) + for _, table := range []struct { + description string + req *types.GetEntriesV1 + wantErr bool + wantReq *types.GetEntriesV1 + }{ + { + description: "invalid: nothing to unpack", + req: nil, + wantErr: true, + }, + { + description: "invalid: start must be larger than end", + req: &types.GetEntriesV1{Start: 1, End: 0}, + wantErr: true, + }, + { + description: "valid: want truncated range", + req: &types.GetEntriesV1{Start: 0, End: uint64(testdata.MaxRange)}, + wantReq: &types.GetEntriesV1{Start: 0, End: uint64(testdata.MaxRange) - 1}, + }, + { + description: "valid", + req: &types.GetEntriesV1{Start: 0, End: 0}, + wantReq: &types.GetEntriesV1{Start: 0, End: 0}, + }, + } { + var buf *bytes.Buffer + if table.req == nil { + buf = bytes.NewBuffer(nil) + } else { + buf = bytes.NewBuffer(marshal(t, *table.req)) + } + + url := EndpointGetEntries.Path("http://example.com", lp.Prefix) + req, err := http.NewRequest("POST", url, buf) + if err != nil { + t.Fatalf("failed creating http request: %v", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + + output, err := lp.parseGetEntriesV1Request(req) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got errror %v but wanted %v in test %q: %v", got, want, table.description, err) + } + if err != nil { + continue + } + if got, want := output, table.wantReq; !reflect.DeepEqual(got, want) { + t.Errorf("got request\n%v\n\tbut wanted\n%v\n\t in test %q", got, want, table.description) + } + } +} + +func TestUnpackOctetPost(t *testing.T) { + for _, table := range []struct { + description string + req *http.Request + out interface{} + wantErr bool + }{ + //{ + // description: "invalid: cannot read request body", + // req: func() *http.Request { + // req, err := http.NewRequest(http.MethodPost, "", iotest.ErrReader(fmt.Errorf("bad reader"))) + // if err != nil { + // t.Fatalf("must make new http request: %v", err) + // } + // return req + // }(), + // out: &types.StItem{}, + // wantErr: true, + //}, // testcase requires Go 1.16 + { + description: "invalid: cannot unmarshal", + req: func() *http.Request { + req, err := http.NewRequest(http.MethodPost, "", bytes.NewBuffer(nil)) + if err != nil { + t.Fatalf("must make new http request: %v", err) + } + return req + }(), + out: &types.StItem{}, + wantErr: true, + }, + { + description: "valid", + req: func() *http.Request { + req, err := http.NewRequest(http.MethodPost, "", bytes.NewBuffer([]byte{0})) + if err != nil { + t.Fatalf("must make new http request: %v", err) + } + return req + }(), + out: &struct{ SomeUint8 uint8 }{}, + }, + } { + err := unpackOctetPost(table.req, table.out) + if got, want := err != nil, table.wantErr; got != want { + t.Errorf("got error %v but wanted %v in test %q", got, want, table.description) + } + } +} + +func marshal(t *testing.T, out interface{}) []byte { + b, err := types.Marshal(out) + if err != nil { + t.Fatalf("must marshal: %v", err) + } + return b +} |