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) } }) } }