blob: d7db6cfa222b581b4ff865a47428bdfe48878ac7 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package driver
import (
"io/ioutil"
"os"
"sync"
tnProto "go.chromium.org/chromiumos/config/go/api/test/harness/tnull/v1"
metadata "go.chromium.org/chromiumos/config/go/api/test/metadata/v1"
rtd "go.chromium.org/chromiumos/config/go/api/test/rtd/v1"
"go.chromium.org/luci/common/errors"
"go.chromium.org/luci/common/sync/parallel"
)
type progressSinkInternalClient struct {
config rtd.ProgressSinkClientConfig
driver *Driver
}
func (c *progressSinkInternalClient) archiveArtifact(req rtd.ArchiveArtifactRequest) rtd.ArchiveArtifactResponse {
panic("Not yet implemented")
}
func (c *progressSinkInternalClient) reportLog(req rtd.ReportLogRequest) rtd.ReportLogResponse {
panic("Not yet implemented")
}
func (c *progressSinkInternalClient) reportResult(req rtd.ReportResultRequest) rtd.ReportResultResponse {
panic("Not yet implemented")
}
func (c *progressSinkInternalClient) debugLog(req interface{}, resp interface{}) rtd.ReportLogResponse {
_ = c.driver.test
panic("Not yet implemented")
}
// Driver is a single-instance object which runs all the operations for a test
type Driver struct {
artifacts []tnProto.MockArtifact
emitResult sync.Once
client *progressSinkInternalClient
config rtd.ProgressSinkClientConfig
logs []tnProto.MockLog
result rtd.Result
test metadata.Test
}
// Setup sets config and prepares a result/logs/artifacts. It is called only once.
func (d *Driver) Setup(test metadata.Test, config rtd.ProgressSinkClientConfig,
result rtd.Result, logs []tnProto.MockLog, artifacts []tnProto.MockArtifact) {
d.test = test
d.config = config
d.client = &progressSinkInternalClient{config: config, driver: d}
d.result = result
d.logs = logs
d.artifacts = artifacts
}
// Archive sends all the stored mock artifacts to the RPC service, in parallel
func (d *Driver) Archive(requestName string) error {
return parallel.WorkPool(0, func(fchan chan<- func() error) {
for _, a := range d.artifacts {
fchan <- func() error {
tmp, err := ioutil.TempFile("", "")
if err != nil {
return errors.Annotate(err, "archiving %s", a.Name).Err()
}
ioutil.WriteFile(tmp.Name(), a.FileBytes, os.ModePerm)
req := rtd.ArchiveArtifactRequest{
Name: a.Name,
Request: requestName,
LocalPath: tmp.Name(),
}
resp := d.client.archiveArtifact(req)
d.client.debugLog(req, resp)
return nil
}
}
})
}
// Log reports all the stored mock logs to the RPC service, in parallel
func (d *Driver) Log(requestName string) error {
return parallel.WorkPool(0, func(fchan chan<- func() error) {
for _, l := range d.logs {
for _, m := range l.Messages {
fchan <- func() error {
req := rtd.ReportLogRequest{
Name: l.Name,
Request: requestName,
Data: []byte(m),
}
resp := d.client.reportLog(req)
d.client.debugLog(req, resp)
return nil
}
}
}
})
}
// Result reports the already-stored result to the RPC service
func (d *Driver) Result(requestName string) error {
var wasFirstTime bool
d.emitResult.Do(func() {
req := rtd.ReportResultRequest{
Request: requestName,
Result: &d.result,
}
resp := d.client.reportResult(req)
d.client.debugLog(req, resp)
wasFirstTime = true
})
if !wasFirstTime {
return errors.Reason("Result cannot be called twice.").Err()
}
return nil
}