Skip to content

Commit c189436

Browse files
authored
test: osvdevexperimental mock paging interface (#3783)
Test this implementation a bit more, and also makes it easier for users to mock their own tests as well. This is to support the work done on moving osvmatcher to osv-scalibr.
1 parent daa101f commit c189436

File tree

2 files changed

+149
-2
lines changed

2 files changed

+149
-2
lines changed

bindings/go/osvdevexperimental/paging.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ import (
77
"osv.dev/bindings/go/osvdev"
88
)
99

10+
type OSVClientInterface interface {
11+
Query(ctx context.Context, query *osvdev.Query) (*osvdev.Response, error)
12+
QueryBatch(ctx context.Context, queries []*osvdev.Query) (*osvdev.BatchedResponse, error)
13+
}
14+
1015
// QueryPaging performs a single query with the given OSVClient, and handles
1116
// paging logic to return all results.
12-
func QueryPaging(ctx context.Context, c *osvdev.OSVClient, query *osvdev.Query) (*osvdev.Response, error) {
17+
func QueryPaging(ctx context.Context, c OSVClientInterface, query *osvdev.Query) (*osvdev.Response, error) {
1318
queryResponse, err := c.Query(ctx, query)
1419

1520
if err != nil {
@@ -56,7 +61,7 @@ func QueryPaging(ctx context.Context, c *osvdev.OSVClient, query *osvdev.Query)
5661

5762
// BatchQueryPaging performs a batch query with the given OSVClient, and handles
5863
// paging logic for each query to return all results.
59-
func BatchQueryPaging(ctx context.Context, c *osvdev.OSVClient, queries []*osvdev.Query) (*osvdev.BatchedResponse, error) {
64+
func BatchQueryPaging(ctx context.Context, c OSVClientInterface, queries []*osvdev.Query) (*osvdev.BatchedResponse, error) {
6065
batchResp, err := c.QueryBatch(ctx, queries)
6166

6267
if err != nil {
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package osvdevexperimental
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/ossf/osv-schema/bindings/go/osvschema"
7+
"testing"
8+
9+
"github.com/google/go-cmp/cmp"
10+
"osv.dev/bindings/go/osvdev"
11+
)
12+
13+
type mockOSVClient struct {
14+
queryResponses map[string]*osvdev.Response
15+
batchQueryReponses map[string]*osvdev.BatchedResponse
16+
}
17+
18+
func (m *mockOSVClient) Query(ctx context.Context, query *osvdev.Query) (*osvdev.Response, error) {
19+
key := query.PageToken
20+
if key == "" {
21+
key = "first"
22+
}
23+
resp, ok := m.queryResponses[key]
24+
if !ok {
25+
return nil, errors.New("no response for query")
26+
}
27+
return resp, nil
28+
}
29+
30+
func (m *mockOSVClient) QueryBatch(ctx context.Context, queries []*osvdev.Query) (*osvdev.BatchedResponse, error) {
31+
// For simplicity, we'll just use the first query's page token to determine the response.
32+
key := ""
33+
if len(queries) > 0 {
34+
key = queries[0].PageToken
35+
}
36+
if key == "" {
37+
key = "first"
38+
}
39+
40+
resp, ok := m.batchQueryReponses[key]
41+
if !ok {
42+
return nil, errors.New("no response for batch query")
43+
}
44+
return resp, nil
45+
}
46+
47+
func TestQueryPaging(t *testing.T) {
48+
mockClient := &mockOSVClient{
49+
queryResponses: map[string]*osvdev.Response{
50+
"first": {
51+
Vulns: []osvschema.Vulnerability{
52+
{ID: "VULN-1"},
53+
},
54+
NextPageToken: "page2",
55+
},
56+
"page2": {
57+
Vulns: []osvschema.Vulnerability{
58+
{ID: "VULN-2"},
59+
},
60+
NextPageToken: "page3",
61+
},
62+
"page3": {
63+
Vulns: []osvschema.Vulnerability{
64+
{ID: "VULN-3"},
65+
},
66+
},
67+
},
68+
}
69+
70+
query := &osvdev.Query{}
71+
resp, err := QueryPaging(context.Background(), mockClient, query)
72+
if err != nil {
73+
t.Fatalf("QueryPaging failed: %v", err)
74+
}
75+
76+
expectedVulns := []osvschema.Vulnerability{
77+
{ID: "VULN-1"},
78+
{ID: "VULN-2"},
79+
{ID: "VULN-3"},
80+
}
81+
82+
if diff := cmp.Diff(expectedVulns, resp.Vulns); diff != "" {
83+
t.Errorf("QueryPaging returned unexpected vulns (-want +got):\n%s", diff)
84+
}
85+
86+
if resp.NextPageToken != "" {
87+
t.Errorf("Expected empty NextPageToken, got %s", resp.NextPageToken)
88+
}
89+
}
90+
91+
func TestBatchQueryPaging(t *testing.T) {
92+
mockClient := &mockOSVClient{
93+
batchQueryReponses: map[string]*osvdev.BatchedResponse{
94+
"first": {
95+
Results: []osvdev.MinimalResponse{
96+
{ // Query 1, Page 1
97+
Vulns: []osvdev.MinimalVulnerability{{ID: "Q1-VULN-1"}},
98+
NextPageToken: "q1page2",
99+
},
100+
{ // Query 2, Page 1
101+
Vulns: []osvdev.MinimalVulnerability{{ID: "Q2-VULN-1"}},
102+
},
103+
},
104+
},
105+
"q1page2": {
106+
Results: []osvdev.MinimalResponse{
107+
{ // Query 1, Page 2
108+
Vulns: []osvdev.MinimalVulnerability{{ID: "Q1-VULN-2"}},
109+
},
110+
},
111+
},
112+
},
113+
}
114+
115+
queries := []*osvdev.Query{
116+
{Commit: "q1"},
117+
{Commit: "q2"},
118+
}
119+
120+
resp, err := BatchQueryPaging(context.Background(), mockClient, queries)
121+
if err != nil {
122+
t.Fatalf("BatchQueryPaging failed: %v", err)
123+
}
124+
125+
expectedResponses := []osvdev.MinimalResponse{
126+
{
127+
Vulns: []osvdev.MinimalVulnerability{
128+
{ID: "Q1-VULN-1"},
129+
{ID: "Q1-VULN-2"},
130+
},
131+
},
132+
{
133+
Vulns: []osvdev.MinimalVulnerability{
134+
{ID: "Q2-VULN-1"},
135+
},
136+
},
137+
}
138+
139+
if diff := cmp.Diff(expectedResponses, resp.Results, cmp.AllowUnexported(osvdev.Response{})); diff != "" {
140+
t.Errorf("BatchQueryPaging returned unexpected results (-want +got):\n%s", diff)
141+
}
142+
}

0 commit comments

Comments
 (0)