|
7 | 7 | "time" |
8 | 8 |
|
9 | 9 | "github.com/google/uuid" |
| 10 | + apierrors "k8s.io/apimachinery/pkg/api/errors" |
10 | 11 | metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" |
11 | 12 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
12 | 13 | "k8s.io/apimachinery/pkg/fields" |
@@ -288,6 +289,87 @@ func TestWatchStopsOnContextCancel(t *testing.T) { |
288 | 289 | assertWatchClosed(t, watcher, watchEventTimeout) |
289 | 290 | } |
290 | 291 |
|
| 292 | +func TestWorkspaceWatchRejectsUnsupportedWatchListOptions(t *testing.T) { |
| 293 | + t.Parallel() |
| 294 | + |
| 295 | + server, _ := newMockCoderServer(t) |
| 296 | + defer server.Close() |
| 297 | + |
| 298 | + workspaceStorage := NewWorkspaceStorage(newTestClientProvider(t, server.URL)) |
| 299 | + defer workspaceStorage.Destroy() |
| 300 | + |
| 301 | + ctx := namespacedContext("control-plane") |
| 302 | + |
| 303 | + t.Run("sendInitialEvents", func(t *testing.T) { |
| 304 | + sendInitialEvents := true |
| 305 | + watcher, err := workspaceStorage.Watch(ctx, &metainternalversion.ListOptions{SendInitialEvents: &sendInitialEvents}) |
| 306 | + assertBadRequestWatchOptionsError(t, watcher, err, "sendInitialEvents") |
| 307 | + }) |
| 308 | + |
| 309 | + t.Run("resourceVersionMatch", func(t *testing.T) { |
| 310 | + watcher, err := workspaceStorage.Watch(ctx, &metainternalversion.ListOptions{ |
| 311 | + ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan, |
| 312 | + }) |
| 313 | + assertBadRequestWatchOptionsError(t, watcher, err, "resourceVersionMatch") |
| 314 | + }) |
| 315 | +} |
| 316 | + |
| 317 | +func TestTemplateWatchRejectsUnsupportedWatchListOptions(t *testing.T) { |
| 318 | + t.Parallel() |
| 319 | + |
| 320 | + server, _ := newMockCoderServer(t) |
| 321 | + defer server.Close() |
| 322 | + |
| 323 | + templateStorage := NewTemplateStorage(newTestClientProvider(t, server.URL)) |
| 324 | + defer templateStorage.Destroy() |
| 325 | + |
| 326 | + ctx := namespacedContext("control-plane") |
| 327 | + |
| 328 | + t.Run("sendInitialEvents", func(t *testing.T) { |
| 329 | + sendInitialEvents := true |
| 330 | + watcher, err := templateStorage.Watch(ctx, &metainternalversion.ListOptions{SendInitialEvents: &sendInitialEvents}) |
| 331 | + assertBadRequestWatchOptionsError(t, watcher, err, "sendInitialEvents") |
| 332 | + }) |
| 333 | + |
| 334 | + t.Run("resourceVersionMatch", func(t *testing.T) { |
| 335 | + watcher, err := templateStorage.Watch(ctx, &metainternalversion.ListOptions{ |
| 336 | + ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan, |
| 337 | + }) |
| 338 | + assertBadRequestWatchOptionsError(t, watcher, err, "resourceVersionMatch") |
| 339 | + }) |
| 340 | +} |
| 341 | + |
| 342 | +func TestValidateUnsupportedWatchListOptions(t *testing.T) { |
| 343 | + t.Parallel() |
| 344 | + |
| 345 | + if err := validateUnsupportedWatchListOptions(nil); err != nil { |
| 346 | + t.Fatalf("expected nil list options to be accepted, got %v", err) |
| 347 | + } |
| 348 | + |
| 349 | + if err := validateUnsupportedWatchListOptions(&metainternalversion.ListOptions{}); err != nil { |
| 350 | + t.Fatalf("expected empty list options to be accepted, got %v", err) |
| 351 | + } |
| 352 | + |
| 353 | + sendInitialEvents := true |
| 354 | + err := validateUnsupportedWatchListOptions(&metainternalversion.ListOptions{SendInitialEvents: &sendInitialEvents}) |
| 355 | + if err == nil { |
| 356 | + t.Fatal("expected sendInitialEvents to be rejected") |
| 357 | + } |
| 358 | + if !strings.Contains(err.Error(), "sendInitialEvents") { |
| 359 | + t.Fatalf("expected sendInitialEvents error, got %v", err) |
| 360 | + } |
| 361 | + |
| 362 | + err = validateUnsupportedWatchListOptions(&metainternalversion.ListOptions{ |
| 363 | + ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan, |
| 364 | + }) |
| 365 | + if err == nil { |
| 366 | + t.Fatal("expected resourceVersionMatch to be rejected") |
| 367 | + } |
| 368 | + if !strings.Contains(err.Error(), "resourceVersionMatch") { |
| 369 | + t.Fatalf("expected resourceVersionMatch error, got %v", err) |
| 370 | + } |
| 371 | +} |
| 372 | + |
291 | 373 | func TestValidateFieldSelector(t *testing.T) { |
292 | 374 | t.Parallel() |
293 | 375 |
|
@@ -459,6 +541,27 @@ func assertWatchClosed(t *testing.T, watcher watch.Interface, timeout time.Durat |
459 | 541 | } |
460 | 542 | } |
461 | 543 |
|
| 544 | +func assertBadRequestWatchOptionsError(t *testing.T, watcher watch.Interface, err error, wantErrSubstring string) { |
| 545 | + t.Helper() |
| 546 | + |
| 547 | + if err == nil { |
| 548 | + if watcher != nil { |
| 549 | + watcher.Stop() |
| 550 | + } |
| 551 | + t.Fatalf("expected watch options error containing %q", wantErrSubstring) |
| 552 | + } |
| 553 | + if watcher != nil { |
| 554 | + watcher.Stop() |
| 555 | + t.Fatalf("expected watcher to be nil when watch options are rejected, got %T", watcher) |
| 556 | + } |
| 557 | + if !apierrors.IsBadRequest(err) { |
| 558 | + t.Fatalf("expected bad request error, got %v", err) |
| 559 | + } |
| 560 | + if !strings.Contains(err.Error(), wantErrSubstring) { |
| 561 | + t.Fatalf("expected error containing %q, got %v", wantErrSubstring, err) |
| 562 | + } |
| 563 | +} |
| 564 | + |
462 | 565 | func templateFromWatchEvent(t *testing.T, evt watch.Event) *aggregationv1alpha1.CoderTemplate { |
463 | 566 | t.Helper() |
464 | 567 |
|
|
0 commit comments