blob: 43288f5a388536509fc0fb7236b3cf0901e6c551 [file] [log] [blame]
// Copyright 2018 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 service
import (
"context"
"fmt"
"reflect"
"testing"
mocks "fuchsia.googlesource.com/infra/infra/tilo/resultstore/service/mocks"
"github.com/golang/mock/gomock"
"github.com/golang/protobuf/ptypes/timestamp"
api "google.golang.org/genproto/googleapis/devtools/resultstore/v2"
"google.golang.org/genproto/protobuf/field_mask"
)
// Public testing constants.
const (
TestLogURI = "http://test.com/log.txt"
TestProjectID = "123456789"
)
// Public testing values.
var (
TestLabels = []string{"test-label"}
TestProperties = map[string]string{"test-property": "test-value"}
TestUsers = []string{"test-user"}
TestUUID = "test-uuid"
TestTimestamp = &timestamp.Timestamp{Seconds: 12345678, Nanos: 99999}
TestInvocationStatus = InvocationSucceeded
TestTargetStatus = TargetSucceeded
TestTestStatus = TestPassed
TestTestSuite = "test-suite"
)
// Test entity keys.
var (
TestInvocationKey = &InvocationKey{
EntityID: &api.Invocation_Id{
InvocationId: "test-invocation",
},
EntityName: "invocations/test-invocation",
}
TestConfigurationKey = &ConfigurationKey{
EntityID: &api.Configuration_Id{
InvocationId: TestInvocationKey.ID(),
ConfigurationId: "test-configuration",
},
EntityName: fmt.Sprintf("invocations/%s/configs/test-configuration",
TestInvocationKey.ID()),
}
TestTargetKey = &TargetKey{
EntityID: &api.Target_Id{
InvocationId: TestInvocationKey.ID(),
TargetId: "test-target",
},
EntityName: fmt.Sprintf("invocations/%s/targets/test-target",
TestInvocationKey.ID()),
}
TestConfiguredTargetKey = &ConfiguredTargetKey{
EntityID: &api.ConfiguredTarget_Id{
InvocationId: TestInvocationKey.ID(),
TargetId: TestTargetKey.ID(),
ConfigurationId: TestConfigurationKey.ID(),
},
EntityName: fmt.Sprintf("invocations/%s/targets/%s/configuredTargets/%s",
TestInvocationKey.ID(),
TestTargetKey.ID(),
TestConfigurationKey.ID()),
}
TestActionKey = &ActionKey{
EntityID: &api.Action_Id{
InvocationId: TestInvocationKey.ID(),
TargetId: TestTargetKey.ID(),
ConfigurationId: TestConfigurationKey.ID(),
ActionId: "test-action",
},
EntityName: fmt.Sprintf(
"invocations/%s/targets/%s/configuredTargets/%s/actions/test-action",
TestInvocationKey.ID(),
TestTargetKey.ID(),
TestConfigurationKey.ID()),
}
)
// TestBed manages the setup and teardown phases of individual test cases.
type TestBed struct {
MockRPCClient *mocks.MockResultStoreUploadClient
ctrl *gomock.Controller
}
// Setup creates the service-under-test and should be run before every test case.
func (bed *TestBed) Setup(t *testing.T) (*Service, context.Context) {
// Cache the mock controller so we can Finish() it during test teardown.
bed.ctrl = gomock.NewController(t)
bed.MockRPCClient = mocks.NewMockResultStoreUploadClient(bed.ctrl)
// Force Service to re-use a fake UUID for testing by embedding the UUID in the
// context object.
ctx, err := SetTestUUID(context.Background(), TestUUID)
if err != nil {
t.Fatal(err)
}
return New(bed.MockRPCClient, TestUUID), ctx
}
// Teardown is used to clean up after every test-case.
func (bed *TestBed) Teardown() {
bed.ctrl.Finish()
}
// ExpectRPC is used to expect that a specific RPC message is recieved by the test bed.
// If an invalid message or no message is received, the test will fail.
func (bed *TestBed) ExpectRPC() *mocks.MockResultStoreUploadClientMockRecorder {
return bed.MockRPCClient.EXPECT()
}
func expectEqual(t *testing.T, expected interface{}, actual interface{}) {
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Objects do not match:\n")
t.Errorf("Expected: %+v\n", expected)
t.Errorf("Actual: %+v\n", actual)
}
}
func TestService_CreateInvocation(t *testing.T) {
t.Run("should return an InvocationKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &Invocation{
ProjectID: TestProjectID,
Users: TestUsers,
Labels: TestLabels,
Properties: TestProperties,
LogURL: TestLogURI,
StartTime: TestTimestamp,
Status: TestInvocationStatus,
}
expectedOutput := TestInvocationKey
testBed.ExpectRPC().
CreateInvocation(ctx, &api.CreateInvocationRequest{
AuthorizationToken: TestUUID,
RequestId: TestUUID,
InvocationId: TestUUID,
Invocation: input.ToResultStoreInvocation(),
}).
Return(&api.Invocation{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.CreateInvocation(ctx, input)
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_UpdateInvocation(t *testing.T) {
t.Run("should return an InvocationKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &Invocation{
ID: TestInvocationKey.ID(),
Properties: TestProperties,
StartTime: TestTimestamp,
}
expectedOutput := TestInvocationKey
testBed.ExpectRPC().
UpdateInvocation(ctx, &api.UpdateInvocationRequest{
AuthorizationToken: TestUUID,
Invocation: input.ToResultStoreInvocation(),
UpdateMask: &field_mask.FieldMask{
Paths: []string{"timing.duration", "status_attributes"},
},
}).
Return(&api.Invocation{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.UpdateInvocation(ctx, input)
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_FinishInvocation(t *testing.T) {
t.Run("should return an InvocationKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
expectedOutput := TestInvocationKey
testBed.ExpectRPC().
FinishInvocation(ctx, &api.FinishInvocationRequest{
AuthorizationToken: TestUUID,
Name: TestInvocationKey.Name(),
}).
Return(&api.FinishInvocationResponse{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.FinishInvocation(ctx, TestInvocationKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_CreateConfiguration(t *testing.T) {
t.Run("should return a ConfigurationKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &Configuration{
ID: TestConfigurationKey.ID(),
InvocationID: TestInvocationKey.ID(),
Properties: TestProperties,
}
expectedOutput := TestConfigurationKey
testBed.ExpectRPC().
CreateConfiguration(ctx, &api.CreateConfigurationRequest{
RequestId: TestUUID,
AuthorizationToken: TestUUID,
Parent: TestInvocationKey.Name(),
ConfigId: input.ID,
Configuration: input.ToResultStoreConfiguration(),
}).
Return(&api.Configuration{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.CreateConfiguration(ctx, input, TestInvocationKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_CreateTarget(t *testing.T) {
t.Run("should return a TargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &Target{
ID: TestTargetKey.ID(),
Properties: TestProperties,
StartTime: TestTimestamp,
Status: TestTargetStatus,
}
expectedOutput := TestTargetKey
testBed.ExpectRPC().
CreateTarget(ctx, &api.CreateTargetRequest{
RequestId: TestUUID,
AuthorizationToken: TestUUID,
Parent: TestInvocationKey.Name(),
TargetId: input.ID,
Target: input.ToResultStoreTarget(),
}).
Return(&api.Target{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.CreateTarget(ctx, input, TestInvocationKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_UpdateTarget(t *testing.T) {
t.Run("should return a TargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &Target{
ID: TestTargetKey.ID(),
InvocationID: TestInvocationKey.ID(),
Properties: TestProperties,
StartTime: TestTimestamp,
}
expectedOutput := TestTargetKey
testBed.ExpectRPC().
UpdateTarget(ctx, &api.UpdateTargetRequest{
AuthorizationToken: TestUUID,
Target: input.ToResultStoreTarget(),
UpdateMask: &field_mask.FieldMask{
Paths: []string{"timing.duration", "status_attributes"},
},
}).
Return(&api.Target{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.UpdateTarget(ctx, input)
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_FinishTarget(t *testing.T) {
t.Run("should return a TargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
expectedOutput := TestTargetKey
testBed.ExpectRPC().
FinishTarget(ctx, &api.FinishTargetRequest{
AuthorizationToken: TestUUID,
Name: TestTargetKey.Name(),
}).
Return(&api.FinishTargetResponse{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.FinishTarget(ctx, TestTargetKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_CreateConfiguredTarget(t *testing.T) {
t.Run("should return a ConfiguredTargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &ConfiguredTarget{
ConfigID: TestConfigurationKey.ID(),
Properties: TestProperties,
StartTime: TestTimestamp,
}
expectedOutput := TestConfiguredTargetKey
testBed.ExpectRPC().
CreateConfiguredTarget(ctx, &api.CreateConfiguredTargetRequest{
AuthorizationToken: TestUUID,
RequestId: TestUUID,
Parent: TestTargetKey.Name(),
ConfigId: TestConfigurationKey.ID(),
ConfiguredTarget: input.ToResultStoreConfiguredTarget(),
}).
Return(&api.ConfiguredTarget{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.CreateConfiguredTarget(ctx, input, TestTargetKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_UpdateConfiguredTarget(t *testing.T) {
t.Run("should return a ConfiguredTargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &ConfiguredTarget{
ConfigID: TestConfiguredTargetKey.ID(),
Properties: TestProperties,
Status: TestTargetStatus,
StartTime: TestTimestamp,
}
expectedOutput := TestConfiguredTargetKey
testBed.ExpectRPC().
UpdateConfiguredTarget(ctx, &api.UpdateConfiguredTargetRequest{
AuthorizationToken: TestUUID,
ConfiguredTarget: input.ToResultStoreConfiguredTarget(),
UpdateMask: &field_mask.FieldMask{
Paths: []string{"timing.duration", "status_attributes"},
},
}).
Return(&api.ConfiguredTarget{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.UpdateConfiguredTarget(ctx, input)
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_FinishConfiguredTarget(t *testing.T) {
t.Run("should return a ConfiguredTargetKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
expectedOutput := TestConfiguredTargetKey
testBed.ExpectRPC().
FinishConfiguredTarget(ctx, &api.FinishConfiguredTargetRequest{
AuthorizationToken: TestUUID,
Name: TestConfiguredTargetKey.Name(),
}).
Return(&api.FinishConfiguredTargetResponse{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.FinishConfiguredTarget(ctx, expectedOutput.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_CreateTestAction(t *testing.T) {
t.Run("should return an ActionKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &TestAction{
ID: TestActionKey.ID(),
InvocationID: TestConfiguredTargetKey.InvocationID(),
TargetID: TestConfiguredTargetKey.TargetID(),
ConfigID: TestConfiguredTargetKey.ConfigurationID(),
TestSuite: TestTestSuite,
TestLogURI: TestLogURI,
StartTime: TestTimestamp,
Status: TestTestStatus,
}
expectedOutput := TestActionKey
testBed.ExpectRPC().
CreateAction(ctx, &api.CreateActionRequest{
RequestId: TestUUID,
AuthorizationToken: TestUUID,
Parent: TestConfiguredTargetKey.Name(),
ActionId: input.ID,
Action: input.ToResultStoreAction(),
}).
Return(&api.Action{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.CreateTestAction(ctx, input, TestConfiguredTargetKey.Name())
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}
func TestService_UpdateTestAction(t *testing.T) {
t.Run("should return an ActionKey from an RPC response", func(t *testing.T) {
testBed := new(TestBed)
service, ctx := testBed.Setup(t)
defer testBed.Teardown()
input := &TestAction{
ID: TestActionKey.ID(),
InvocationID: TestConfiguredTargetKey.InvocationID(),
TargetID: TestConfiguredTargetKey.TargetID(),
ConfigID: TestConfiguredTargetKey.ConfigurationID(),
TestSuite: TestTestSuite,
TestLogURI: TestLogURI,
StartTime: TestTimestamp,
}
expectedOutput := TestActionKey
testBed.ExpectRPC().
UpdateAction(ctx, &api.UpdateActionRequest{
AuthorizationToken: TestUUID,
Action: input.ToResultStoreAction(),
UpdateMask: &field_mask.FieldMask{
Paths: []string{"timing.duration", "status_attributes"},
},
}).
Return(&api.Action{
Name: expectedOutput.EntityName,
Id: expectedOutput.EntityID,
}, nil)
output, err := service.UpdateTestAction(ctx, input)
if err != nil {
t.Fatal(err)
}
expectEqual(t, expectedOutput, output)
})
}