diff options
Diffstat (limited to 'pkg/coveragedb')
| -rw-r--r-- | pkg/coveragedb/coveragedb.go | 57 | ||||
| -rw-r--r-- | pkg/coveragedb/coveragedb_mock_test.go | 23 |
2 files changed, 59 insertions, 21 deletions
diff --git a/pkg/coveragedb/coveragedb.go b/pkg/coveragedb/coveragedb.go index 6741e72d1..8272ce6ff 100644 --- a/pkg/coveragedb/coveragedb.go +++ b/pkg/coveragedb/coveragedb.go @@ -85,14 +85,11 @@ type fileSubsystems struct { } func SaveMergeResult(ctx context.Context, client spannerclient.SpannerClient, descr *HistoryRecord, dec *json.Decoder, - sss []*subsystem.Subsystem) (int, error) { +) (int, error) { if client == nil { return 0, fmt.Errorf("nil spannerclient") } var rowsCreated int - ssMatcher := subsystem.MakePathMatcher(sss) - ssCache := make(map[string][]string) - session := uuid.New().String() var mutations []*spanner.Mutation @@ -107,8 +104,6 @@ func SaveMergeResult(ctx context.Context, client spannerclient.SpannerClient, de } if mcr := wr.MCR; mcr != nil { mutations = append(mutations, fileRecordMutation(session, mcr)) - subsystems := getFileSubsystems(mcr.FilePath, ssMatcher, ssCache) - mutations = append(mutations, fileSubsystemsMutation(descr.Namespace, mcr.FilePath, subsystems)) } else if fl := wr.FL; fl != nil { mutations = append(mutations, fileFunctionsMutation(session, fl)) } else { @@ -627,3 +622,53 @@ func UniqCoverage(fullCov, partCov map[int]int64) map[int]int64 { } return res } + +func RegenerateSubsystems(ctx context.Context, ns string, sss []*subsystem.Subsystem, + client spannerclient.SpannerClient) (int, error) { + ssMatcher := subsystem.MakePathMatcher(sss) + ssCache := make(map[string][]string) + filePaths, err := getFilePaths(ctx, ns, client) + if err != nil { + return 0, err + } + var mutations []*spanner.Mutation + for _, filePath := range filePaths { + subsystems := getFileSubsystems(filePath, ssMatcher, ssCache) + mutations = append(mutations, fileSubsystemsMutation(ns, filePath, subsystems)) + } + // There is a limit on the number of mutations per transaction (80k) imposed by the DB. + // Expected mutations count is < 20k and looks safe to do w/o batching. + if _, err = client.Apply(ctx, mutations); err != nil { + return 0, err + } + return len(mutations), nil +} + +func getFilePaths(ctx context.Context, ns string, client spannerclient.SpannerClient) ([]string, error) { + iter := client.Single().Query(ctx, spanner.Statement{ + SQL: `select filepath from file_subsystems where namespace=$1`, + Params: map[string]interface{}{ + "p1": ns, + }, + }) + defer iter.Stop() + + var res []string + for { + row, err := iter.Next() + if err == iterator.Done { + break + } + if err != nil { + return nil, fmt.Errorf("iter.Next: %w", err) + } + var r struct { + Filepath string + } + if err = row.ToStruct(&r); err != nil { + return nil, fmt.Errorf("row.ToStruct: %w", err) + } + res = append(res, r.Filepath) + } + return res, nil +} diff --git a/pkg/coveragedb/coveragedb_mock_test.go b/pkg/coveragedb/coveragedb_mock_test.go index 23676d31f..f7efd479a 100644 --- a/pkg/coveragedb/coveragedb_mock_test.go +++ b/pkg/coveragedb/coveragedb_mock_test.go @@ -4,7 +4,6 @@ package coveragedb import ( - "context" "encoding/json" "io" "strings" @@ -13,7 +12,6 @@ import ( "cloud.google.com/go/spanner" "github.com/google/syzkaller/pkg/coveragedb/mocks" - "github.com/google/syzkaller/pkg/subsystem" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -23,7 +21,6 @@ type spannerMockTune func(*testing.T, *mocks.SpannerClient) func TestSaveMergeResult(t *testing.T) { tests := []struct { name string - sss []*subsystem.Subsystem jsonl io.Reader descr *HistoryRecord mockTune spannerMockTune @@ -45,7 +42,7 @@ func TestSaveMergeResult(t *testing.T) { name: "1 MCR record, Ok", jsonl: strings.NewReader(`{"MCR":{"FileData":{}}}`), descr: &HistoryRecord{}, - wantRows: 3, // 1 in files, 1 in file_subsystems and 1 in merge_history + wantRows: 2, // 1 in files and 1 in merge_history mockTune: func(t *testing.T, m *mocks.SpannerClient) { m. On("Apply", mock.Anything, mock.Anything). @@ -71,14 +68,14 @@ func TestSaveMergeResult(t *testing.T) { jsonl: strings.NewReader(` {"MCR":{"FileData":{}}} {"MCR":{"FileData":{}}}`), descr: &HistoryRecord{}, - wantRows: 5, + wantRows: 3, mockTune: func(t *testing.T, m *mocks.SpannerClient) { m. On("Apply", mock.Anything, mock.MatchedBy(func(ms []*spanner.Mutation) bool { - // 2 in files, 2 in file_subsystems and 1 in merge_history - return len(ms) == 5 + // 2 in files and 1 in merge_history + return len(ms) == 3 })). Return(time.Now(), nil). Once() @@ -88,17 +85,17 @@ func TestSaveMergeResult(t *testing.T) { name: "2k records, Ok", jsonl: strings.NewReader(strings.Repeat("{\"MCR\":{\"FileData\":{}}}\n", 2000)), descr: &HistoryRecord{}, - wantRows: 4001, + wantRows: 2001, mockTune: func(t *testing.T, m *mocks.SpannerClient) { m. On("Apply", mock.Anything, mock.MatchedBy(func(ms []*spanner.Mutation) bool { - // 2k in files, 2k in file_subsystems + // 2k in files return len(ms) == 1000 })). Return(time.Now(), nil). - Times(4). + Times(2). On("Apply", mock.Anything, mock.MatchedBy(func(ms []*spanner.Mutation) bool { @@ -117,11 +114,7 @@ func TestSaveMergeResult(t *testing.T) { if test.mockTune != nil { test.mockTune(t, spannerMock) } - gotRows, err := SaveMergeResult( - context.Background(), - spannerMock, - test.descr, - json.NewDecoder(test.jsonl), test.sss) + gotRows, err := SaveMergeResult(t.Context(), spannerMock, test.descr, json.NewDecoder(test.jsonl)) if test.wantErr { assert.Error(t, err) } else { |
