github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/controller/testutil.go (about)

     1  // Copyright 2025 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package controller
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"net/http/httptest"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/google/syzkaller/syz-cluster/pkg/api"
    14  	"github.com/google/syzkaller/syz-cluster/pkg/app"
    15  	"github.com/google/syzkaller/syz-cluster/pkg/db"
    16  	"github.com/stretchr/testify/assert"
    17  )
    18  
    19  type EntityIDs struct {
    20  	SeriesID  string
    21  	SessionID string
    22  }
    23  
    24  // UploadTestSeries returns a (series ID, session ID) tuple.
    25  func UploadTestSeries(t *testing.T, ctx context.Context,
    26  	client *api.Client, series *api.Series) EntityIDs {
    27  	retSeries, err := client.UploadSeries(ctx, series)
    28  	assert.NoError(t, err)
    29  	retSession, err := client.UploadSession(ctx, &api.NewSession{
    30  		ExtID: series.ExtID,
    31  	})
    32  	assert.NoError(t, err)
    33  	return EntityIDs{
    34  		SeriesID:  retSeries.ID,
    35  		SessionID: retSession.ID,
    36  	}
    37  }
    38  
    39  func UploadTestBuild(t *testing.T, ctx context.Context, client *api.Client,
    40  	build *api.Build) *api.UploadBuildResp {
    41  	ret, err := client.UploadBuild(ctx, &api.UploadBuildReq{
    42  		Build:  *build,
    43  		Log:    []byte("build log"),
    44  		Config: []byte("build config"),
    45  	})
    46  	assert.NoError(t, err)
    47  	assert.NotEmpty(t, ret.ID)
    48  	return ret
    49  }
    50  
    51  func TestServer(t *testing.T, env *app.AppEnvironment) *api.Client {
    52  	apiServer := NewAPIServer(env)
    53  	server := httptest.NewServer(apiServer.Mux())
    54  	t.Cleanup(server.Close)
    55  	return api.NewClient(server.URL)
    56  }
    57  
    58  func DummySeries() *api.Series {
    59  	return &api.Series{
    60  		ExtID: "ext-id",
    61  		Title: "test series name",
    62  		Link:  "http://link/to/series",
    63  		Cc:    []string{"first@user.com", "second@user.com"},
    64  		Patches: []api.SeriesPatch{
    65  			{
    66  				Seq:   1,
    67  				Title: "first patch title",
    68  				Body:  []byte("first content"),
    69  			},
    70  		},
    71  	}
    72  }
    73  
    74  func DummyBuild() *api.Build {
    75  	return &api.Build{
    76  		Arch:       "amd64",
    77  		TreeName:   "mainline",
    78  		TreeURL:    "https://git/repo",
    79  		ConfigName: "config",
    80  		CommitHash: "abcd",
    81  		Compiler:   "compiler",
    82  	}
    83  }
    84  
    85  func DummyFindings() []*api.NewFinding {
    86  	var findings []*api.NewFinding
    87  	for i := 0; i < 2; i++ {
    88  		findings = append(findings, &api.NewFinding{
    89  			Title:    fmt.Sprintf("finding %d", i),
    90  			TestName: "test",
    91  			Report:   []byte(fmt.Sprintf("report %d", i)),
    92  			Log:      []byte(fmt.Sprintf("log %d", i)),
    93  			SyzRepro: []byte(fmt.Sprintf("log %d", i)),
    94  			CRepro:   []byte(fmt.Sprintf("log %d", i)),
    95  		})
    96  	}
    97  	return findings
    98  }
    99  
   100  type SeriesWithFindingIDs struct {
   101  	EntityIDs
   102  	BaseBuildID    string
   103  	PatchedBuildID string
   104  }
   105  
   106  func FakeSeriesWithFindings(t *testing.T, ctx context.Context, env *app.AppEnvironment,
   107  	client *api.Client, series *api.Series) SeriesWithFindingIDs {
   108  	ids := UploadTestSeries(t, ctx, client, series)
   109  	baseBuild := UploadTestBuild(t, ctx, client, DummyBuild())
   110  	patchedBuild := UploadTestBuild(t, ctx, client, DummyBuild())
   111  	err := client.UploadTestResult(ctx, &api.TestResult{
   112  		SessionID:      ids.SessionID,
   113  		BaseBuildID:    baseBuild.ID,
   114  		PatchedBuildID: patchedBuild.ID,
   115  		TestName:       "test",
   116  		Result:         api.TestRunning,
   117  	})
   118  	assert.NoError(t, err)
   119  
   120  	findings := DummyFindings()
   121  	for _, finding := range findings {
   122  		finding.SessionID = ids.SessionID
   123  		err = client.UploadFinding(ctx, finding)
   124  		assert.NoError(t, err)
   125  	}
   126  	MarkSessionFinished(t, env, ids.SessionID)
   127  	return SeriesWithFindingIDs{
   128  		EntityIDs:      ids,
   129  		BaseBuildID:    baseBuild.ID,
   130  		PatchedBuildID: patchedBuild.ID,
   131  	}
   132  }
   133  
   134  func MarkSessionFinished(t *testing.T, env *app.AppEnvironment, sessionID string) {
   135  	repo := db.NewSessionRepository(env.Spanner)
   136  	err := repo.Update(context.Background(), sessionID, func(session *db.Session) error {
   137  		session.SetFinishedAt(time.Now())
   138  		return nil
   139  	})
   140  	assert.NoError(t, err)
   141  }