Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: complete workload unit tests #475

Merged
merged 1 commit into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (g *appConfigurationGenerator) Generate(spec *models.Spec) error {

gfs := []appconfiguration.NewGeneratorFunc{
NewNamespaceGeneratorFunc(g.project.Name),
workload.NewWorkloadGeneratorFunc(g.project, g.stack, g.app.Workload, g.appName),
workload.NewWorkloadGeneratorFunc(g.project, g.stack, g.appName, g.app.Workload),
}

if err := appconfiguration.CallGenerators(spec, gfs...); err != nil {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package workload

import (
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"kusionstack.io/kusion/pkg/generator/appconfiguration"
"kusionstack.io/kusion/pkg/models"
"kusionstack.io/kusion/pkg/models/appconfiguration/workload"
"kusionstack.io/kusion/pkg/projectstack"
)

func TestNewJobGenerator(t *testing.T) {
expectedProject := &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
}
expectedStack := &projectstack.Stack{}
expectedAppName := "test"
expectedJob := &workload.Job{}
actual, err := NewJobGenerator(expectedProject, expectedStack, expectedAppName, expectedJob)

assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, actual, "Generator should not be nil")
assert.Equal(t, expectedProject, actual.(*jobGenerator).project, "Project mismatch")
assert.Equal(t, expectedStack, actual.(*jobGenerator).stack, "Stack mismatch")
assert.Equal(t, expectedAppName, actual.(*jobGenerator).appName, "AppName mismatch")
assert.Equal(t, expectedJob, actual.(*jobGenerator).job, "Job mismatch")
}

func TestNewJobGeneratorFunc(t *testing.T) {
expectedProject := &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
}
expectedStack := &projectstack.Stack{}
expectedAppName := "test"
expectedJob := &workload.Job{}
generatorFunc := NewJobGeneratorFunc(expectedProject, expectedStack, expectedAppName, expectedJob)
actualGenerator, err := generatorFunc()

assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, actualGenerator, "Generator should not be nil")
assert.Equal(t, expectedProject, actualGenerator.(*jobGenerator).project, "Project mismatch")
assert.Equal(t, expectedStack, actualGenerator.(*jobGenerator).stack, "Stack mismatch")
assert.Equal(t, expectedAppName, actualGenerator.(*jobGenerator).appName, "AppName mismatch")
assert.Equal(t, expectedJob, actualGenerator.(*jobGenerator).job, "Job mismatch")
}

func TestJobGenerator_Generate(t *testing.T) {
testCases := []struct {
name string
expectedProject *projectstack.Project
expectedStack *projectstack.Stack
expectedAppName string
expectedJob *workload.Job
}{
{
name: "test generate",
expectedProject: &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
},
expectedStack: &projectstack.Stack{},
expectedAppName: "test",
expectedJob: &workload.Job{},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
generator, _ := NewJobGenerator(tc.expectedProject, tc.expectedStack, tc.expectedAppName, tc.expectedJob)
spec := &models.Spec{}
err := generator.Generate(spec)

assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, spec.Resources, "Resources should not be nil")
assert.Len(t, spec.Resources, 1, "Number of resources mismatch")

// Check the generated resource
resource := spec.Resources[0]
actual := mapToUnstructured(resource.Attributes)

assert.Equal(t, "Job", actual.GetKind(), "Kind mismatch")
assert.Equal(t, tc.expectedProject.Name, actual.GetNamespace(), "Namespace mismatch")
assert.Equal(t, appconfiguration.UniqueAppName(tc.expectedProject.Name, tc.expectedStack.Name, tc.expectedAppName), actual.GetName(), "Name mismatch")
assert.Equal(t, appconfiguration.MergeMaps(appconfiguration.UniqueAppLabels(tc.expectedProject.Name, tc.expectedAppName), tc.expectedJob.Labels), actual.GetLabels(), "Labels mismatch")
assert.Equal(t, appconfiguration.MergeMaps(tc.expectedJob.Annotations), actual.GetAnnotations(), "Annotations mismatch")
})
}
}

func mapToUnstructured(data map[string]interface{}) *unstructured.Unstructured {
unstructuredObj := &unstructured.Unstructured{}
unstructuredObj.SetUnstructuredContent(data)
return unstructuredObj
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ type workloadGenerator struct {
func NewWorkloadGenerator(
project *projectstack.Project,
stack *projectstack.Stack,
workload *workload.Workload,
appName string,
workload *workload.Workload,
) (appconfiguration.Generator, error) {
if len(project.Name) == 0 {
return nil, fmt.Errorf("project name must not be empty")
Expand All @@ -40,11 +40,11 @@ func NewWorkloadGenerator(
func NewWorkloadGeneratorFunc(
project *projectstack.Project,
stack *projectstack.Stack,
workload *workload.Workload,
appName string,
workload *workload.Workload,
) appconfiguration.NewGeneratorFunc {
return func() (appconfiguration.Generator, error) {
return NewWorkloadGenerator(project, stack, workload, appName)
return NewWorkloadGenerator(project, stack, appName, workload)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package workload

import (
"testing"

"github.com/stretchr/testify/assert"
"kusionstack.io/kusion/pkg/generator/appconfiguration"
"kusionstack.io/kusion/pkg/models"
"kusionstack.io/kusion/pkg/models/appconfiguration/workload"
"kusionstack.io/kusion/pkg/models/appconfiguration/workload/container"
"kusionstack.io/kusion/pkg/projectstack"
)

func TestNewWorkloadGenerator(t *testing.T) {
t.Run("NewWorkloadGenerator should return a valid generator", func(t *testing.T) {
expectedProject := &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
}
expectedStack := &projectstack.Stack{}
expectedWorkload := &workload.Workload{}
expectedAppName := "test"

actualGenerator, err := NewWorkloadGenerator(expectedProject, expectedStack, expectedAppName, expectedWorkload)

assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, actualGenerator, "Generator should not be nil")
assert.Equal(t, expectedProject, actualGenerator.(*workloadGenerator).project, "Project mismatch")
assert.Equal(t, expectedStack, actualGenerator.(*workloadGenerator).stack, "Stack mismatch")
assert.Equal(t, expectedAppName, actualGenerator.(*workloadGenerator).appName, "AppName mismatch")
assert.Equal(t, expectedWorkload, actualGenerator.(*workloadGenerator).workload, "Workload mismatch")
})
}

func TestNewWorkloadGeneratorFunc(t *testing.T) {
t.Run("NewWorkloadGeneratorFunc should return a valid generator function", func(t *testing.T) {
expectedProject := &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
}
expectedStack := &projectstack.Stack{}
expectedWorkload := &workload.Workload{}
expectedAppName := "test"

generatorFunc := NewWorkloadGeneratorFunc(expectedProject, expectedStack, expectedAppName, expectedWorkload)
actualGenerator, err := generatorFunc()

assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, actualGenerator, "Generator should not be nil")
assert.Equal(t, expectedProject, actualGenerator.(*workloadGenerator).project, "Project mismatch")
assert.Equal(t, expectedStack, actualGenerator.(*workloadGenerator).stack, "Stack mismatch")
assert.Equal(t, expectedAppName, actualGenerator.(*workloadGenerator).appName, "AppName mismatch")
assert.Equal(t, expectedWorkload, actualGenerator.(*workloadGenerator).workload, "Workload mismatch")
})
}

func TestWorkloadGenerator_Generate(t *testing.T) {
testCases := []struct {
name string
expectedWorkload *workload.Workload
}{
{
name: "Generate should generate the expected service",
expectedWorkload: &workload.Workload{
Header: workload.Header{
Type: "Service",
},
Service: &workload.Service{
Base: workload.Base{},
Type: "Deployment",
},
},
},
{
name: "Generate should generate the expected job",
expectedWorkload: &workload.Workload{
Header: workload.Header{
Type: "Job",
},
Job: &workload.Job{
Base: workload.Base{},
Schedule: "* * * * *",
},
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
expectedProject := &projectstack.Project{
ProjectConfiguration: projectstack.ProjectConfiguration{
Name: "test",
},
}
expectedStack := &projectstack.Stack{}
expectedAppName := "test"
actualGenerator, _ := NewWorkloadGenerator(expectedProject, expectedStack, expectedAppName, tc.expectedWorkload)
spec := &models.Spec{}
err := actualGenerator.Generate(spec)
assert.NoError(t, err, "Error should be nil")
assert.NotNil(t, spec.Resources, "Resources should not be nil")
assert.Len(t, spec.Resources, 1, "Number of resources mismatch")

// Check the generated resource
resource := spec.Resources[0]
actual := mapToUnstructured(resource.Attributes)

assert.Equal(t, expectedProject.Name, actual.GetNamespace(), "Namespace mismatch")
assert.Equal(t, appconfiguration.UniqueAppName(expectedProject.Name, expectedStack.Name, expectedAppName), actual.GetName(), "Name mismatch")

if tc.expectedWorkload.Header.Type == "Service" {
assert.Equal(t, "Deployment", actual.GetKind(), "Resource kind mismatch")
assert.Equal(t, appconfiguration.MergeMaps(appconfiguration.UniqueAppLabels(expectedProject.Name, expectedAppName), tc.expectedWorkload.Service.Labels), actual.GetLabels(), "Labels mismatch")
assert.Equal(t, appconfiguration.MergeMaps(tc.expectedWorkload.Service.Annotations), actual.GetAnnotations(), "Annotations mismatch")
} else if tc.expectedWorkload.Header.Type == "Job" {
assert.Equal(t, "CronJob", actual.GetKind(), "Resource kind mismatch")
assert.Equal(t, appconfiguration.MergeMaps(appconfiguration.UniqueAppLabels(expectedProject.Name, expectedAppName), tc.expectedWorkload.Job.Labels), actual.GetLabels(), "Labels mismatch")
assert.Equal(t, appconfiguration.MergeMaps(tc.expectedWorkload.Job.Annotations), actual.GetAnnotations(), "Annotations mismatch")
}
})
}
}

func TestToOrderedContainers(t *testing.T) {
t.Run("toOrderedContainers should convert app containers to ordered containers", func(t *testing.T) {
appContainers := make(map[string]container.Container)
appContainers["container1"] = container.Container{
Image: "image1",
Env: make(map[string]string),
}
appContainers["container2"] = container.Container{
Image: "image2",
Env: map[string]string{"key": "value"},
}

actualContainers, err := toOrderedContainers(appContainers)

assert.NoError(t, err, "Error should be nil")
assert.Len(t, actualContainers, 2, "Number of containers mismatch")
assert.Equal(t, "container1", actualContainers[0].Name, "Container name mismatch")
assert.Equal(t, "image1", actualContainers[0].Image, "Container image mismatch")
assert.Equal(t, "container2", actualContainers[1].Name, "Container name mismatch")
assert.Equal(t, "image2", actualContainers[1].Image, "Container image mismatch")
assert.Len(t, actualContainers[1].Env, 1, "Number of env vars mismatch")
assert.Equal(t, "key", actualContainers[1].Env[0].Name, "Env var name mismatch")
assert.Equal(t, "value", actualContainers[1].Env[0].Value, "Env var value mismatch")
})
}
5 changes: 4 additions & 1 deletion pkg/generator/appconfiguration/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,17 @@ func MergeMaps(maps ...map[string]string) map[string]string {
merged := make(map[string]string)

for _, m := range maps {
if m == nil {
if len(m) == 0 {
continue
}
for k, v := range m {
merged[k] = v
}
}

if len(merged) == 0 {
return nil
}
return merged
}

Expand Down
Loading