|
@@ -18,10 +18,12 @@ package compose
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "fmt"
|
|
|
"testing"
|
|
|
|
|
|
"github.com/compose-spec/compose-go/types"
|
|
|
"github.com/stretchr/testify/require"
|
|
|
+ "gotest.tools/assert"
|
|
|
)
|
|
|
|
|
|
var project = types.Project{
|
|
@@ -69,3 +71,181 @@ func TestInDependencyReverseDownCommandOrder(t *testing.T) {
|
|
|
require.NoError(t, err, "Error during iteration")
|
|
|
require.Equal(t, []string{"test1", "test2", "test3"}, order)
|
|
|
}
|
|
|
+
|
|
|
+func TestBuildGraph(t *testing.T) {
|
|
|
+ testCases := []struct {
|
|
|
+ desc string
|
|
|
+ services types.Services
|
|
|
+ expectedVertices map[string]*Vertex
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ desc: "builds graph with single service",
|
|
|
+ services: types.Services{
|
|
|
+ {
|
|
|
+ Name: "test",
|
|
|
+ DependsOn: types.DependsOnConfig{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ expectedVertices: map[string]*Vertex{
|
|
|
+ "test": {
|
|
|
+ Key: "test",
|
|
|
+ Service: "test",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{},
|
|
|
+ Parents: map[string]*Vertex{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ desc: "builds graph with two separate services",
|
|
|
+ services: types.Services{
|
|
|
+ {
|
|
|
+ Name: "test",
|
|
|
+ DependsOn: types.DependsOnConfig{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Name: "another",
|
|
|
+ DependsOn: types.DependsOnConfig{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ expectedVertices: map[string]*Vertex{
|
|
|
+ "test": {
|
|
|
+ Key: "test",
|
|
|
+ Service: "test",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{},
|
|
|
+ Parents: map[string]*Vertex{},
|
|
|
+ },
|
|
|
+ "another": {
|
|
|
+ Key: "another",
|
|
|
+ Service: "another",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{},
|
|
|
+ Parents: map[string]*Vertex{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ desc: "builds graph with a service and a dependency",
|
|
|
+ services: types.Services{
|
|
|
+ {
|
|
|
+ Name: "test",
|
|
|
+ DependsOn: types.DependsOnConfig{
|
|
|
+ "another": types.ServiceDependency{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Name: "another",
|
|
|
+ DependsOn: types.DependsOnConfig{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ expectedVertices: map[string]*Vertex{
|
|
|
+ "test": {
|
|
|
+ Key: "test",
|
|
|
+ Service: "test",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{
|
|
|
+ "another": {},
|
|
|
+ },
|
|
|
+ Parents: map[string]*Vertex{},
|
|
|
+ },
|
|
|
+ "another": {
|
|
|
+ Key: "another",
|
|
|
+ Service: "another",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{},
|
|
|
+ Parents: map[string]*Vertex{
|
|
|
+ "test": {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ desc: "builds graph with multiple dependency levels",
|
|
|
+ services: types.Services{
|
|
|
+ {
|
|
|
+ Name: "test",
|
|
|
+ DependsOn: types.DependsOnConfig{
|
|
|
+ "another": types.ServiceDependency{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Name: "another",
|
|
|
+ DependsOn: types.DependsOnConfig{
|
|
|
+ "another_dep": types.ServiceDependency{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Name: "another_dep",
|
|
|
+ DependsOn: types.DependsOnConfig{},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ expectedVertices: map[string]*Vertex{
|
|
|
+ "test": {
|
|
|
+ Key: "test",
|
|
|
+ Service: "test",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{
|
|
|
+ "another": {},
|
|
|
+ },
|
|
|
+ Parents: map[string]*Vertex{},
|
|
|
+ },
|
|
|
+ "another": {
|
|
|
+ Key: "another",
|
|
|
+ Service: "another",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{
|
|
|
+ "another_dep": {},
|
|
|
+ },
|
|
|
+ Parents: map[string]*Vertex{
|
|
|
+ "test": {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "another_dep": {
|
|
|
+ Key: "another_dep",
|
|
|
+ Service: "another_dep",
|
|
|
+ Status: ServiceStopped,
|
|
|
+ Children: map[string]*Vertex{},
|
|
|
+ Parents: map[string]*Vertex{
|
|
|
+ "another": {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ }
|
|
|
+ for _, tC := range testCases {
|
|
|
+ t.Run(tC.desc, func(t *testing.T) {
|
|
|
+ project := types.Project{
|
|
|
+ Services: tC.services,
|
|
|
+ }
|
|
|
+
|
|
|
+ graph, err := NewGraph(project.Services, ServiceStopped)
|
|
|
+ assert.NilError(t, err, fmt.Sprintf("failed to build graph for: %s", tC.desc))
|
|
|
+
|
|
|
+ for k, vertex := range graph.Vertices {
|
|
|
+ expected, ok := tC.expectedVertices[k]
|
|
|
+ assert.Equal(t, true, ok)
|
|
|
+ assert.Equal(t, true, isVertexEqual(*expected, *vertex))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func isVertexEqual(a, b Vertex) bool {
|
|
|
+ childrenEquality := true
|
|
|
+ for c := range a.Children {
|
|
|
+ if _, ok := b.Children[c]; !ok {
|
|
|
+ childrenEquality = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ parentEquality := true
|
|
|
+ for p := range a.Parents {
|
|
|
+ if _, ok := b.Parents[p]; !ok {
|
|
|
+ parentEquality = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return a.Key == b.Key &&
|
|
|
+ a.Service == b.Service &&
|
|
|
+ childrenEquality &&
|
|
|
+ parentEquality
|
|
|
+}
|