blob: 86613e8f80aae5a9cc0d1cf15cedd7c073bd95e4 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 main
import (
"context"
"math/rand"
"time"
"fuchsia.googlesource.com/infra/infra/resultstore"
"fuchsia.googlesource.com/infra/infra/resultstore/fields"
"github.com/google/uuid"
)
// Dummy test log URLs.
const (
passingTestLogURL = "gs://fuchsia-infra-test/tilo_passed_test.log"
failingTestLogURL = "gs://fuchsia-infra-test/tilo_failed_test.log"
)
// simulator is used to simulate the execution of a collection of tests in ResultStore.
// The simulator is useful for the duration of a single invocation's lifetime. It is also
// assumed that the invocation takes place within a single test configuration.
type simulator struct {
client resultstore.UploadClient
configuration *resultstore.Configuration
invocation *resultstore.Invocation
random *rand.Rand
}
func NewSimulator(ctx context.Context, client resultstore.UploadClient, projectID, configurationID string, seed int64) (*simulator, error) {
// Create the invocation for this Simulation.
startTime := time.Now()
invocation, err := client.CreateInvocation(ctx, &resultstore.Invocation{
ProjectID: projectID,
ID: uuid.New().String(),
StartTime: startTime,
})
if err != nil {
return nil, err
}
invocation.StartTime = startTime
// Create the environment for this Simulation.
configuration, err := client.CreateConfiguration(ctx, &resultstore.Configuration{
ID: configurationID,
InvocationID: invocation.ID,
Properties: map[string]string{
"a": "b",
"c": "d",
},
}, invocation.Name)
if err != nil {
return nil, err
}
return &simulator{
client: client,
configuration: configuration,
invocation: invocation,
random: rand.New(rand.NewSource(seed)),
}, nil
}
// Returns the URL to this simulator's Invocation in Result Store.
func (s *simulator) InvocationURL() string {
return resultstore.Staging.InvocationURL(s.invocation.ID)
}
// End finishes this simulator's invocation.
func (s *simulator) End(ctx context.Context, status resultstore.Status) error {
s.invocation.Status = status
s.invocation.Duration = 10 * time.Minute
if _, err := s.client.UpdateInvocation(ctx, s.invocation, []string{
fields.StatusAttributes,
fields.Duration,
}); err != nil {
return err
}
return s.client.FinishInvocation(ctx, s.invocation.Name)
}
// Test simulates the execution of a test with the given name.
func (s *simulator) Test(ctx context.Context, test string) (resultstore.Status, error) {
var status resultstore.Status
// Create a test target for the test.
startTime := time.Now()
target, err := s.client.CreateTarget(ctx, &resultstore.Target{
ID: &resultstore.TargetID{
ID: test,
InvocationID: s.invocation.ID,
},
StartTime: startTime,
}, s.invocation.Name)
if err != nil {
return resultstore.Unknown, err
}
// Create a ConfiguredTarget for the target
configuredTarget, err := s.client.CreateConfiguredTarget(ctx, &resultstore.ConfiguredTarget{
ID: &resultstore.ConfiguredTargetID{
InvocationID: s.invocation.ID,
TargetID: target.ID.ID,
ConfigID: s.configuration.ID,
},
StartTime: startTime,
}, target.Name)
if err != nil {
return resultstore.Unknown, err
}
// Create a test action the configured target.
action, err := s.client.CreateTestAction(ctx, &resultstore.TestAction{
ID: &resultstore.TestActionID{
ID: "test",
InvocationID: s.invocation.ID,
TargetID: target.ID.ID,
ConfigID: configuredTarget.ID.ConfigID,
},
StartTime: startTime,
}, configuredTarget.Name)
if err != nil {
return resultstore.Unknown, err
}
// Update that the test has finished
const duration = 10 * time.Minute
logURL := passingTestLogURL
status = resultstore.Passed
if s.random.Intn(2) < 1 {
status = resultstore.Failed
logURL = failingTestLogURL
}
action.StartTime = startTime
action.Duration = duration
action.TestLogURI = logURL
action.Status = status
if _, err := s.client.UpdateTestAction(ctx, action, []string{
fields.Duration,
fields.Files,
fields.StatusAttributes,
}); err != nil {
return resultstore.Unknown, err
}
configuredTarget.StartTime = startTime
configuredTarget.Duration = duration
configuredTarget.Status = status
if _, err := s.client.UpdateConfiguredTarget(ctx, configuredTarget, []string{
fields.Duration,
fields.StatusAttributes,
}); err != nil {
return resultstore.Unknown, err
}
target.StartTime = startTime
target.Duration = duration
target.Status = status
target.TestLogURI = logURL
if _, err := s.client.UpdateTarget(ctx, target, []string{
fields.Duration,
fields.Files,
fields.StatusAttributes,
}); err != nil {
return resultstore.Unknown, err
}
if err := s.client.FinishConfiguredTarget(ctx, configuredTarget.Name); err != nil {
return resultstore.Unknown, err
}
if err := s.client.FinishTarget(ctx, target.Name); err != nil {
return resultstore.Unknown, err
}
return status, nil
}