penguin/monok8s

k8s image for Mono Gateway Dev Kit

clitools/pkg/controller/osupgrade/planner_test.go

raw ยท 3677 bytes

package osupgrade

import (
	"reflect"
	"testing"
)

func TestCalculatePath(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name      string
		current   string
		target    string
		available []string
		want      []string
		wantErr   bool
	}{
		{
			name:      "same version returns nil path",
			current:   "v1.34.6",
			target:    "v1.34.6",
			available: []string{"v1.34.6"},
			want:      nil,
			wantErr:   false,
		},
		{
			name:      "same minor jumps directly to target",
			current:   "v1.34.1",
			target:    "v1.34.6",
			available: []string{"v1.34.1", "v1.34.3", "v1.34.6"},
			want:      []string{"v1.34.6"},
			wantErr:   false,
		},
		{
			name:      "next minor direct jump when no current minor patch available",
			current:   "v1.34.6",
			target:    "v1.35.3",
			available: []string{"v1.34.6", "v1.35.1", "v1.35.3"},
			want:      []string{"v1.35.3"},
			wantErr:   false,
		},
		{
			name:      "finish current minor then target",
			current:   "v1.34.1",
			target:    "v1.35.3",
			available: []string{"v1.34.1", "v1.34.6", "v1.35.1", "v1.35.3"},
			want:      []string{"v1.34.6", "v1.35.3"},
			wantErr:   false,
		},
		{
			name:      "multi minor path uses latest bridge patch",
			current:   "v1.33.10",
			target:    "v1.35.3",
			available: []string{"v1.34.1", "v1.34.6", "v1.35.1", "v1.35.3"},
			want:      []string{"v1.34.6", "v1.35.3"},
			wantErr:   false,
		},
		{
			name:      "multi minor path finishes current minor and latest bridge patch",
			current:   "v1.33.1",
			target:    "v1.35.3",
			available: []string{"v1.33.5", "v1.33.9", "v1.34.1", "v1.34.6", "v1.35.3"},
			want:      []string{"v1.33.9", "v1.34.6", "v1.35.3"},
			wantErr:   false,
		},
		{
			name:      "duplicates in available are ignored",
			current:   "v1.33.10",
			target:    "v1.35.3",
			available: []string{"v1.34.6", "v1.34.6", "v1.35.3", "v1.35.3"},
			want:      []string{"v1.34.6", "v1.35.3"},
			wantErr:   false,
		},
		{
			name:      "target missing returns error",
			current:   "v1.34.6",
			target:    "v1.35.3",
			available: []string{"v1.34.6", "v1.35.1"},
			wantErr:   true,
		},
		{
			name:      "missing bridge minor returns error",
			current:   "v1.33.10",
			target:    "v1.35.3",
			available: []string{"v1.35.3"},
			wantErr:   true,
		},
		{
			name:      "downgrade not supported",
			current:   "v1.35.3",
			target:    "v1.34.6",
			available: []string{"v1.34.6", "v1.35.3"},
			wantErr:   true,
		},
		{
			name:      "cross major not supported",
			current:   "v1.35.3",
			target:    "v2.0.0",
			available: []string{"v1.35.3", "v2.0.0"},
			wantErr:   true,
		},
		{
			name:      "invalid current version returns error",
			current:   "garbage",
			target:    "v1.35.3",
			available: []string{"v1.35.3"},
			wantErr:   true,
		},
		{
			name:      "invalid target version returns error",
			current:   "v1.34.6",
			target:    "wat",
			available: []string{"v1.34.6", "v1.35.3"},
			wantErr:   true,
		},
		{
			name:      "invalid available version returns error",
			current:   "v1.34.6",
			target:    "v1.35.3",
			available: []string{"v1.34.6", "broken", "v1.35.3"},
			wantErr:   true,
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			got, err := calculatePath(tt.current, tt.target, tt.available)
			if tt.wantErr {
				if err == nil {
					t.Fatalf("expected error, got nil; path=%v", got)
				}
				return
			}

			if err != nil {
				t.Fatalf("unexpected error: %v", err)
			}

			if !reflect.DeepEqual(got, tt.want) {
				t.Fatalf("calculatePath(%q, %q, %v)\n got:  %v\n want: %v",
					tt.current, tt.target, tt.available, got, tt.want)
			}
		})
	}
}