mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-16 01:22:00 +00:00
chore: more gateway tests
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mulgadc/hive/hive/utils"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDescribeInstanceTypes_SingleNode(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
{InstanceType: aws.String("t3.small")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.InstanceTypes, 2)
|
||||
assert.Equal(t, "t3.micro", *output.InstanceTypes[0].InstanceType)
|
||||
assert.Equal(t, "t3.small", *output.InstanceTypes[1].InstanceType)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_DeduplicatesAcrossNodes(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// Node 1
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
{InstanceType: aws.String("t3.small")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
// Node 2 reports same types
|
||||
nc2, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
defer nc2.Close()
|
||||
|
||||
nc2.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
{InstanceType: aws.String("m5.large")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
nc.Flush()
|
||||
nc2.Flush()
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 2)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
// t3.micro should appear once, t3.small once, m5.large once = 3 unique
|
||||
assert.Len(t, output.InstanceTypes, 3)
|
||||
|
||||
seen := make(map[string]int)
|
||||
for _, it := range output.InstanceTypes {
|
||||
seen[*it.InstanceType]++
|
||||
}
|
||||
assert.Equal(t, 1, seen["t3.micro"])
|
||||
assert.Equal(t, 1, seen["t3.small"])
|
||||
assert.Equal(t, 1, seen["m5.large"])
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_CapacityFilterShowsDuplicates(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// Node 1
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
// Node 2 reports same type
|
||||
nc2, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
defer nc2.Close()
|
||||
|
||||
nc2.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
nc.Flush()
|
||||
nc2.Flush()
|
||||
|
||||
// With capacity filter = true, duplicates should be preserved
|
||||
input := &ec2.DescribeInstanceTypesInput{
|
||||
Filters: []*ec2.Filter{
|
||||
{
|
||||
Name: aws.String("capacity"),
|
||||
Values: []*string{aws.String("true")},
|
||||
},
|
||||
},
|
||||
}
|
||||
output, err := DescribeInstanceTypes(input, nc, 2)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
// Both slots should appear since capacity filter is enabled
|
||||
assert.Len(t, output.InstanceTypes, 2)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_CapacityFilterFalseDeduplicates(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
// capacity=false should still deduplicate
|
||||
input := &ec2.DescribeInstanceTypesInput{
|
||||
Filters: []*ec2.Filter{
|
||||
{
|
||||
Name: aws.String("capacity"),
|
||||
Values: []*string{aws.String("false")},
|
||||
},
|
||||
},
|
||||
}
|
||||
output, err := DescribeInstanceTypes(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.InstanceTypes, 1)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_NoSubscribers(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 0)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.InstanceTypes)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_NodeReturnsError(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
errorPayload := utils.GenerateErrorPayload("InternalError")
|
||||
msg.Respond(errorPayload)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.InstanceTypes)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_MalformedJSON(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`not valid json`))
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.InstanceTypes)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_NilInstanceTypeSkipped(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstanceTypes", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstanceTypesOutput{
|
||||
InstanceTypes: []*ec2.InstanceTypeInfo{
|
||||
{InstanceType: aws.String("t3.micro")},
|
||||
{InstanceType: nil}, // nil InstanceType should be skipped in dedup
|
||||
nil, // nil entry should be skipped
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
output, err := DescribeInstanceTypes(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.InstanceTypes, 1)
|
||||
assert.Equal(t, "t3.micro", *output.InstanceTypes[0].InstanceType)
|
||||
}
|
||||
|
||||
func TestDescribeInstanceTypes_ClosedConnection(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
closedNC, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
closedNC.Close()
|
||||
|
||||
input := &ec2.DescribeInstanceTypesInput{}
|
||||
_, err = DescribeInstanceTypes(input, closedNC, 1)
|
||||
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mulgadc/hive/hive/utils"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDescribeInstances_SingleNode(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
reservation := &ec2.Reservation{
|
||||
ReservationId: aws.String("r-abc123"),
|
||||
Instances: []*ec2.Instance{
|
||||
{
|
||||
InstanceId: aws.String("i-001"),
|
||||
InstanceType: aws.String("t3.micro"),
|
||||
State: &ec2.InstanceState{Code: aws.Int64(16), Name: aws.String("running")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{reservation},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
require.Len(t, output.Reservations, 1)
|
||||
assert.Equal(t, "r-abc123", *output.Reservations[0].ReservationId)
|
||||
assert.Equal(t, "i-001", *output.Reservations[0].Instances[0].InstanceId)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_MultipleNodes(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// Two nodes each return different instances
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
{
|
||||
ReservationId: aws.String("r-node1"),
|
||||
Instances: []*ec2.Instance{
|
||||
{InstanceId: aws.String("i-node1-001")},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
nc2, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
defer nc2.Close()
|
||||
|
||||
nc2.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
{
|
||||
ReservationId: aws.String("r-node2"),
|
||||
Instances: []*ec2.Instance{
|
||||
{InstanceId: aws.String("i-node2-001")},
|
||||
{InstanceId: aws.String("i-node2-002")},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
// Wait for subscriptions to propagate
|
||||
nc.Flush()
|
||||
nc2.Flush()
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 2)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.Reservations, 2)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_NoSubscribers(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 0)
|
||||
|
||||
// No subscribers means timeout — function returns empty reservations, no error
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.Reservations)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_NodeReturnsError(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
errorPayload := utils.GenerateErrorPayload("InternalError")
|
||||
msg.Respond(errorPayload)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 1)
|
||||
|
||||
// Error responses from nodes are logged but don't fail the overall call
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.Reservations)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_MixedResponses(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// Node 1: returns valid data
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
{
|
||||
ReservationId: aws.String("r-good"),
|
||||
Instances: []*ec2.Instance{{InstanceId: aws.String("i-good")}},
|
||||
},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
// Node 2: returns error
|
||||
nc2, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
defer nc2.Close()
|
||||
|
||||
nc2.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
errorPayload := utils.GenerateErrorPayload("InternalError")
|
||||
msg.Respond(errorPayload)
|
||||
})
|
||||
|
||||
nc.Flush()
|
||||
nc2.Flush()
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 2)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
// Only the valid node's reservation should appear
|
||||
assert.Len(t, output.Reservations, 1)
|
||||
assert.Equal(t, "r-good", *output.Reservations[0].ReservationId)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_MalformedJSON(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{invalid json`))
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 1)
|
||||
|
||||
// Malformed JSON from a node is skipped, not fatal
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.Reservations)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_EmptyReservations(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: nil,
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 1)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Empty(t, output.Reservations)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_TimeoutCollection(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// Node responds after a delay (but within timeout)
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
{ReservationId: aws.String("r-delayed")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
output, err := DescribeInstances(input, nc, 0) // 0 = timeout-based collection
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.Reservations, 1)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_EarlyExitWithExpectedNodes(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
nc.Subscribe("ec2.DescribeInstances", func(msg *nats.Msg) {
|
||||
data, _ := json.Marshal(&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
{ReservationId: aws.String("r-fast")},
|
||||
},
|
||||
})
|
||||
msg.Respond(data)
|
||||
})
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
start := time.Now()
|
||||
output, err := DescribeInstances(input, nc, 1)
|
||||
duration := time.Since(start)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.Reservations, 1)
|
||||
// Should exit early, well before the 3-second timeout
|
||||
assert.Less(t, duration, 2*time.Second)
|
||||
}
|
||||
|
||||
func TestDescribeInstances_ClosedConnection(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
closedNC, err := nats.Connect(nc.ConnectedUrl())
|
||||
require.NoError(t, err)
|
||||
closedNC.Close()
|
||||
|
||||
input := &ec2.DescribeInstancesInput{}
|
||||
_, err = DescribeInstances(input, closedNC, 1)
|
||||
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -115,6 +115,68 @@ func TestParseRunInstances(t *testing.T) {
|
||||
want: errors.New(awserrors.ErrorInvalidAMIIDMalformed),
|
||||
},
|
||||
|
||||
{
|
||||
name: "NilInput",
|
||||
input: nil,
|
||||
want: errors.New(awserrors.ErrorMissingParameter),
|
||||
},
|
||||
|
||||
{
|
||||
name: "NilMinCount",
|
||||
input: &ec2.RunInstancesInput{
|
||||
ImageId: defaults.ImageId,
|
||||
InstanceType: defaults.InstanceType,
|
||||
MinCount: nil,
|
||||
MaxCount: aws.Int64(1),
|
||||
KeyName: defaults.KeyName,
|
||||
SecurityGroupIds: defaults.SecurityGroupIds,
|
||||
SubnetId: defaults.SubnetId,
|
||||
},
|
||||
want: errors.New(awserrors.ErrorMissingParameter),
|
||||
},
|
||||
|
||||
{
|
||||
name: "MinCountGreaterThanMaxCount",
|
||||
input: &ec2.RunInstancesInput{
|
||||
ImageId: defaults.ImageId,
|
||||
InstanceType: defaults.InstanceType,
|
||||
MinCount: aws.Int64(5),
|
||||
MaxCount: aws.Int64(2),
|
||||
KeyName: defaults.KeyName,
|
||||
SecurityGroupIds: defaults.SecurityGroupIds,
|
||||
SubnetId: defaults.SubnetId,
|
||||
},
|
||||
want: errors.New(awserrors.ErrorInvalidParameterValue),
|
||||
},
|
||||
|
||||
{
|
||||
name: "NilImageId",
|
||||
input: &ec2.RunInstancesInput{
|
||||
ImageId: nil,
|
||||
InstanceType: defaults.InstanceType,
|
||||
MinCount: aws.Int64(1),
|
||||
MaxCount: aws.Int64(1),
|
||||
KeyName: defaults.KeyName,
|
||||
SecurityGroupIds: defaults.SecurityGroupIds,
|
||||
SubnetId: defaults.SubnetId,
|
||||
},
|
||||
want: errors.New(awserrors.ErrorMissingParameter),
|
||||
},
|
||||
|
||||
{
|
||||
name: "NilInstanceType",
|
||||
input: &ec2.RunInstancesInput{
|
||||
ImageId: defaults.ImageId,
|
||||
InstanceType: nil,
|
||||
MinCount: aws.Int64(1),
|
||||
MaxCount: aws.Int64(1),
|
||||
KeyName: defaults.KeyName,
|
||||
SecurityGroupIds: defaults.SecurityGroupIds,
|
||||
SubnetId: defaults.SubnetId,
|
||||
},
|
||||
want: errors.New(awserrors.ErrorMissingParameter),
|
||||
},
|
||||
|
||||
// Successful test
|
||||
{
|
||||
name: "ValidTest",
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mulgadc/hive/hive/qmp"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStartInstances_Success(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-0123456789abcdef0"
|
||||
|
||||
// Mock subscriber for the instance command topic
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
var cmd qmp.Command
|
||||
err := json.Unmarshal(msg.Data, &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, instanceID, cmd.ID)
|
||||
assert.Equal(t, "cont", cmd.QMPCommand.Execute)
|
||||
assert.True(t, cmd.Attributes.StartInstance)
|
||||
assert.False(t, cmd.Attributes.StopInstance)
|
||||
assert.False(t, cmd.Attributes.TerminateInstance)
|
||||
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := StartInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
require.Len(t, output.StartingInstances, 1)
|
||||
|
||||
sc := output.StartingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(0), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "pending", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(80), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "stopped", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestStartInstances_MultipleInstances(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
ids := []string{"i-001", "i-002", "i-003"}
|
||||
|
||||
for _, id := range ids {
|
||||
id := id
|
||||
nc.Subscribe("ec2.cmd."+id, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
}
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{aws.String(ids[0]), aws.String(ids[1]), aws.String(ids[2])},
|
||||
}
|
||||
|
||||
output, err := StartInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
assert.Len(t, output.StartingInstances, 3)
|
||||
|
||||
for i, sc := range output.StartingInstances {
|
||||
assert.Equal(t, ids[i], *sc.InstanceId)
|
||||
assert.Equal(t, "pending", *sc.CurrentState.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartInstances_EmptyInstanceIds(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{},
|
||||
}
|
||||
|
||||
_, err := StartInstances(input, nc)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "no instance IDs provided")
|
||||
}
|
||||
|
||||
func TestStartInstances_NilInstanceIdSkipped(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-valid"
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{nil, aws.String(instanceID), nil},
|
||||
}
|
||||
|
||||
output, err := StartInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
// Only the valid ID should produce a state change
|
||||
assert.Len(t, output.StartingInstances, 1)
|
||||
assert.Equal(t, instanceID, *output.StartingInstances[0].InstanceId)
|
||||
}
|
||||
|
||||
func TestStartInstances_NATSRequestFails(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
// No subscriber for this instance topic, so NATS request will fail
|
||||
instanceID := "i-nosubscriber"
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := StartInstances(input, nc)
|
||||
|
||||
require.NoError(t, err) // Function itself doesn't error, it records state change
|
||||
require.NotNil(t, output)
|
||||
require.Len(t, output.StartingInstances, 1)
|
||||
|
||||
// On NATS failure, state should reflect "still stopped"
|
||||
sc := output.StartingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(80), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "stopped", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(80), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "stopped", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestStartInstances_MixedSuccessAndFailure(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
goodID := "i-good"
|
||||
badID := "i-bad" // no subscriber
|
||||
|
||||
nc.Subscribe("ec2.cmd."+goodID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StartInstancesInput{
|
||||
InstanceIds: []*string{aws.String(goodID), aws.String(badID)},
|
||||
}
|
||||
|
||||
output, err := StartInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.StartingInstances, 2)
|
||||
|
||||
// First instance succeeded: state → pending
|
||||
assert.Equal(t, goodID, *output.StartingInstances[0].InstanceId)
|
||||
assert.Equal(t, "pending", *output.StartingInstances[0].CurrentState.Name)
|
||||
|
||||
// Second instance failed: state → stopped (unchanged)
|
||||
assert.Equal(t, badID, *output.StartingInstances[1].InstanceId)
|
||||
assert.Equal(t, "stopped", *output.StartingInstances[1].CurrentState.Name)
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mulgadc/hive/hive/qmp"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestStopInstances_Success(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-0123456789abcdef0"
|
||||
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
var cmd qmp.Command
|
||||
err := json.Unmarshal(msg.Data, &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, instanceID, cmd.ID)
|
||||
assert.Equal(t, "system_powerdown", cmd.QMPCommand.Execute)
|
||||
assert.True(t, cmd.Attributes.StopInstance)
|
||||
assert.False(t, cmd.Attributes.TerminateInstance)
|
||||
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := StopInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
require.Len(t, output.StoppingInstances, 1)
|
||||
|
||||
sc := output.StoppingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(64), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "stopping", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(16), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestStopInstances_MultipleInstances(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
ids := []string{"i-001", "i-002"}
|
||||
|
||||
for _, id := range ids {
|
||||
id := id
|
||||
nc.Subscribe("ec2.cmd."+id, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
}
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{aws.String(ids[0]), aws.String(ids[1])},
|
||||
}
|
||||
|
||||
output, err := StopInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.StoppingInstances, 2)
|
||||
|
||||
for i, sc := range output.StoppingInstances {
|
||||
assert.Equal(t, ids[i], *sc.InstanceId)
|
||||
assert.Equal(t, "stopping", *sc.CurrentState.Name)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStopInstances_EmptyInstanceIds(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{},
|
||||
}
|
||||
|
||||
_, err := StopInstances(input, nc)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "no instance IDs provided")
|
||||
}
|
||||
|
||||
func TestStopInstances_NilInstanceIdSkipped(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-valid"
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{nil, aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := StopInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, output.StoppingInstances, 1)
|
||||
assert.Equal(t, instanceID, *output.StoppingInstances[0].InstanceId)
|
||||
}
|
||||
|
||||
func TestStopInstances_NATSRequestFails(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-nosubscriber"
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := StopInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.StoppingInstances, 1)
|
||||
|
||||
// On NATS failure, state should reflect "still running"
|
||||
sc := output.StoppingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(16), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "running", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(16), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestStopInstances_MixedSuccessAndFailure(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
goodID := "i-good"
|
||||
badID := "i-bad"
|
||||
|
||||
nc.Subscribe("ec2.cmd."+goodID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.StopInstancesInput{
|
||||
InstanceIds: []*string{aws.String(goodID), aws.String(badID)},
|
||||
}
|
||||
|
||||
output, err := StopInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.StoppingInstances, 2)
|
||||
|
||||
// First: success → stopping
|
||||
assert.Equal(t, goodID, *output.StoppingInstances[0].InstanceId)
|
||||
assert.Equal(t, "stopping", *output.StoppingInstances[0].CurrentState.Name)
|
||||
|
||||
// Second: failure → still running
|
||||
assert.Equal(t, badID, *output.StoppingInstances[1].InstanceId)
|
||||
assert.Equal(t, "running", *output.StoppingInstances[1].CurrentState.Name)
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/mulgadc/hive/hive/qmp"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTerminateInstances_Success(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-0123456789abcdef0"
|
||||
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
var cmd qmp.Command
|
||||
err := json.Unmarshal(msg.Data, &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, instanceID, cmd.ID)
|
||||
assert.Equal(t, "system_powerdown", cmd.QMPCommand.Execute)
|
||||
assert.True(t, cmd.Attributes.StopInstance)
|
||||
assert.True(t, cmd.Attributes.TerminateInstance)
|
||||
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := TerminateInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, output)
|
||||
require.Len(t, output.TerminatingInstances, 1)
|
||||
|
||||
sc := output.TerminatingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(32), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "shutting-down", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(16), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestTerminateInstances_MultipleInstances(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
ids := []string{"i-001", "i-002", "i-003"}
|
||||
|
||||
for _, id := range ids {
|
||||
id := id
|
||||
nc.Subscribe("ec2.cmd."+id, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
}
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{aws.String(ids[0]), aws.String(ids[1]), aws.String(ids[2])},
|
||||
}
|
||||
|
||||
output, err := TerminateInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.TerminatingInstances, 3)
|
||||
|
||||
for i, sc := range output.TerminatingInstances {
|
||||
assert.Equal(t, ids[i], *sc.InstanceId)
|
||||
assert.Equal(t, "shutting-down", *sc.CurrentState.Name)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTerminateInstances_EmptyInstanceIds(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{},
|
||||
}
|
||||
|
||||
_, err := TerminateInstances(input, nc)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "no instance IDs provided")
|
||||
}
|
||||
|
||||
func TestTerminateInstances_NilInstanceIdSkipped(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-valid"
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{nil, aws.String(instanceID), nil},
|
||||
}
|
||||
|
||||
output, err := TerminateInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, output.TerminatingInstances, 1)
|
||||
assert.Equal(t, instanceID, *output.TerminatingInstances[0].InstanceId)
|
||||
}
|
||||
|
||||
func TestTerminateInstances_NATSRequestFails(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-nosubscriber"
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
output, err := TerminateInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.TerminatingInstances, 1)
|
||||
|
||||
// On NATS failure, state should reflect "still running"
|
||||
sc := output.TerminatingInstances[0]
|
||||
assert.Equal(t, instanceID, *sc.InstanceId)
|
||||
assert.Equal(t, int64(16), *sc.CurrentState.Code)
|
||||
assert.Equal(t, "running", *sc.CurrentState.Name)
|
||||
assert.Equal(t, int64(16), *sc.PreviousState.Code)
|
||||
assert.Equal(t, "running", *sc.PreviousState.Name)
|
||||
}
|
||||
|
||||
func TestTerminateInstances_MixedSuccessAndFailure(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
goodID := "i-good"
|
||||
badID := "i-bad"
|
||||
|
||||
nc.Subscribe("ec2.cmd."+goodID, func(msg *nats.Msg) {
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{aws.String(goodID), aws.String(badID)},
|
||||
}
|
||||
|
||||
output, err := TerminateInstances(input, nc)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, output.TerminatingInstances, 2)
|
||||
|
||||
// First: success → shutting-down
|
||||
assert.Equal(t, goodID, *output.TerminatingInstances[0].InstanceId)
|
||||
assert.Equal(t, "shutting-down", *output.TerminatingInstances[0].CurrentState.Name)
|
||||
|
||||
// Second: failure → still running
|
||||
assert.Equal(t, badID, *output.TerminatingInstances[1].InstanceId)
|
||||
assert.Equal(t, "running", *output.TerminatingInstances[1].CurrentState.Name)
|
||||
}
|
||||
|
||||
func TestTerminateInstances_VerifiesQMPAttributes(t *testing.T) {
|
||||
_, nc := startTestNATSServer(t)
|
||||
|
||||
instanceID := "i-verify"
|
||||
var receivedCmd qmp.Command
|
||||
|
||||
nc.Subscribe("ec2.cmd."+instanceID, func(msg *nats.Msg) {
|
||||
json.Unmarshal(msg.Data, &receivedCmd)
|
||||
msg.Respond([]byte(`{"return":{}}`))
|
||||
})
|
||||
|
||||
input := &ec2.TerminateInstancesInput{
|
||||
InstanceIds: []*string{aws.String(instanceID)},
|
||||
}
|
||||
|
||||
_, err := TerminateInstances(input, nc)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Terminate should set both stop and terminate flags
|
||||
assert.True(t, receivedCmd.Attributes.StopInstance, "StopInstance should be true for terminate")
|
||||
assert.True(t, receivedCmd.Attributes.TerminateInstance, "TerminateInstance should be true")
|
||||
assert.False(t, receivedCmd.Attributes.StartInstance, "StartInstance should be false")
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package gateway_ec2_instance
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// startTestNATSServer starts an embedded NATS server for testing
|
||||
func startTestNATSServer(t *testing.T) (*server.Server, *nats.Conn) {
|
||||
t.Helper()
|
||||
|
||||
opts := &server.Options{
|
||||
Host: "127.0.0.1",
|
||||
Port: -1,
|
||||
JetStream: false,
|
||||
NoLog: true,
|
||||
NoSigs: true,
|
||||
}
|
||||
|
||||
ns, err := server.NewServer(opts)
|
||||
require.NoError(t, err, "Failed to create NATS server")
|
||||
|
||||
go ns.Start()
|
||||
|
||||
if !ns.ReadyForConnections(5 * time.Second) {
|
||||
t.Fatal("NATS server failed to start")
|
||||
}
|
||||
|
||||
nc, err := nats.Connect(ns.ClientURL())
|
||||
require.NoError(t, err, "Failed to connect to NATS")
|
||||
|
||||
t.Cleanup(func() {
|
||||
nc.Close()
|
||||
ns.Shutdown()
|
||||
})
|
||||
|
||||
return ns, nc
|
||||
}
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Run Go tests with coverage and report total code coverage.
|
||||
|
||||
COVERPROFILE=$(mktemp /tmp/hive-coverage-XXXXXX.out)
|
||||
trap 'rm -f "$COVERPROFILE"' EXIT
|
||||
|
||||
echo "Running tests with coverage..."
|
||||
echo ""
|
||||
LOG_IGNORE=1 go test -timeout 120s -coverprofile="$COVERPROFILE" -covermode=atomic ./hive/... 2>&1
|
||||
|
||||
if [[ ! -s "$COVERPROFILE" ]]; then
|
||||
echo "No coverage data collected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Total ==="
|
||||
go tool cover -func="$COVERPROFILE" | awk '/^total:/ { print $NF }'
|
||||
Reference in New Issue
Block a user