(t *testing.T)
| 68 | } |
| 69 | |
| 70 | func TestServeHTTP_FailureModes(t *testing.T) { |
| 71 | t.Parallel() |
| 72 | |
| 73 | defaultHeaders := map[string]string{"Authorization": "Bearer key"} |
| 74 | httpClient := &http.Client{} |
| 75 | |
| 76 | cases := []struct { |
| 77 | name string |
| 78 | reqHeaders map[string]string |
| 79 | applyMocksFn func(client *mock.MockDRPCClient, pool *mock.MockPooler) |
| 80 | dialerFn aibridged.Dialer |
| 81 | contextFn func() context.Context |
| 82 | expectedErr error |
| 83 | expectedStatus int |
| 84 | }{ |
| 85 | // Authnz-related failures. |
| 86 | { |
| 87 | name: "no auth key", |
| 88 | reqHeaders: make(map[string]string), |
| 89 | expectedErr: aibridged.ErrNoAuthKey, |
| 90 | expectedStatus: http.StatusBadRequest, |
| 91 | }, |
| 92 | { |
| 93 | name: "unrecognized header", |
| 94 | reqHeaders: map[string]string{ |
| 95 | codersdk.SessionTokenHeader: "key", // Coder-Session-Token is not supported; requests originate with AI clients, not coder CLI. |
| 96 | }, |
| 97 | applyMocksFn: func(client *mock.MockDRPCClient, _ *mock.MockPooler) {}, |
| 98 | expectedErr: aibridged.ErrNoAuthKey, |
| 99 | expectedStatus: http.StatusBadRequest, |
| 100 | }, |
| 101 | { |
| 102 | name: "unauthorized", |
| 103 | applyMocksFn: func(client *mock.MockDRPCClient, _ *mock.MockPooler) { |
| 104 | client.EXPECT().IsAuthorized(gomock.Any(), gomock.Any()).AnyTimes().Return(nil, xerrors.New("not authorized")) |
| 105 | }, |
| 106 | expectedErr: aibridged.ErrUnauthorized, |
| 107 | expectedStatus: http.StatusForbidden, |
| 108 | }, |
| 109 | { |
| 110 | name: "invalid key owner ID", |
| 111 | applyMocksFn: func(client *mock.MockDRPCClient, _ *mock.MockPooler) { |
| 112 | client.EXPECT().IsAuthorized(gomock.Any(), gomock.Any()).AnyTimes().Return(&proto.IsAuthorizedResponse{OwnerId: "oops"}, nil) |
| 113 | }, |
| 114 | expectedErr: aibridged.ErrUnauthorized, |
| 115 | expectedStatus: http.StatusForbidden, |
| 116 | }, |
| 117 | |
| 118 | // TODO: coderd connection-related failures. |
| 119 | |
| 120 | // Pool-related failures. |
| 121 | { |
| 122 | name: "pool instance", |
| 123 | applyMocksFn: func(client *mock.MockDRPCClient, pool *mock.MockPooler) { |
| 124 | // Should pass authorization. |
| 125 | client.EXPECT().IsAuthorized(gomock.Any(), gomock.Any()).AnyTimes().Return(&proto.IsAuthorizedResponse{OwnerId: uuid.NewString()}, nil) |
| 126 | // But fail when acquiring a pool instance. |
| 127 | pool.EXPECT().Acquire(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil, xerrors.New("oops")) |
nothing calls this directly
no test coverage detected