mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
@ -99,6 +99,7 @@ func diffValues[T any](left, right T, table Table) Map {
|
||||
}
|
||||
|
||||
// convertDiffType converts external struct types to primitive types.
|
||||
//
|
||||
//nolint:forcetypeassert
|
||||
func convertDiffType(left, right any) (newLeft, newRight any, changed bool) {
|
||||
switch typed := left.(type) {
|
||||
|
@ -230,6 +230,7 @@ func runDiffTests[T audit.Auditable](t *testing.T, tests []diffTest[T]) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(typName+"/"+test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
require.Equal(t,
|
||||
test.exp,
|
||||
audit.Diff(test.left, test.right),
|
||||
|
@ -31,6 +31,7 @@ func AuthorizeFilter[O rbac.Objecter](api *API, r *http.Request, action rbac.Act
|
||||
// This function will log appropriately, but the caller must return an
|
||||
// error to the api client.
|
||||
// Eg:
|
||||
//
|
||||
// if !api.Authorize(...) {
|
||||
// httpapi.Forbidden(rw)
|
||||
// return
|
||||
|
@ -20,14 +20,14 @@ type Notifier struct {
|
||||
}
|
||||
|
||||
// Condition is a function that gets executed with a certain time.
|
||||
// - It should return the deadline for the notification, as well as a
|
||||
// callback function to execute once the time to the deadline is
|
||||
// less than one of the notify attempts. If deadline is the zero
|
||||
// time, callback will not be executed.
|
||||
// - Callback is executed once for every time the difference between deadline
|
||||
// and the current time is less than an element of countdown.
|
||||
// - To enforce a minimum interval between consecutive callbacks, truncate
|
||||
// the returned deadline to the minimum interval.
|
||||
// - It should return the deadline for the notification, as well as a
|
||||
// callback function to execute once the time to the deadline is
|
||||
// less than one of the notify attempts. If deadline is the zero
|
||||
// time, callback will not be executed.
|
||||
// - Callback is executed once for every time the difference between deadline
|
||||
// and the current time is less than an element of countdown.
|
||||
// - To enforce a minimum interval between consecutive callbacks, truncate
|
||||
// the returned deadline to the minimum interval.
|
||||
type Condition func(now time.Time) (deadline time.Time, callback func())
|
||||
|
||||
// Notify is a convenience function that initializes a new Notifier
|
||||
@ -44,8 +44,8 @@ func Notify(cond Condition, interval time.Duration, countdown ...time.Duration)
|
||||
}
|
||||
|
||||
// New returns a Notifier that calls cond once every time it polls.
|
||||
// - Duplicate values are removed from countdown, and it is sorted in
|
||||
// descending order.
|
||||
// - Duplicate values are removed from countdown, and it is sorted in
|
||||
// descending order.
|
||||
func New(cond Condition, countdown ...time.Duration) *Notifier {
|
||||
// Ensure countdown is sorted in descending order and contains no duplicates.
|
||||
ct := unique(countdown)
|
||||
|
@ -28,13 +28,14 @@ var defaultParser = cron.NewParser(parserFormat)
|
||||
// - day of week e.g. 1 (required)
|
||||
//
|
||||
// Example Usage:
|
||||
// local_sched, _ := schedule.Weekly("59 23 *")
|
||||
// fmt.Println(sched.Next(time.Now().Format(time.RFC3339)))
|
||||
// // Output: 2022-04-04T23:59:00Z
|
||||
//
|
||||
// us_sched, _ := schedule.Weekly("CRON_TZ=US/Central 30 9 1-5")
|
||||
// fmt.Println(sched.Next(time.Now()).Format(time.RFC3339))
|
||||
// // Output: 2022-04-04T14:30:00Z
|
||||
// local_sched, _ := schedule.Weekly("59 23 *")
|
||||
// fmt.Println(sched.Next(time.Now().Format(time.RFC3339)))
|
||||
// // Output: 2022-04-04T23:59:00Z
|
||||
//
|
||||
// us_sched, _ := schedule.Weekly("CRON_TZ=US/Central 30 9 1-5")
|
||||
// fmt.Println(sched.Next(time.Now()).Format(time.RFC3339))
|
||||
// // Output: 2022-04-04T14:30:00Z
|
||||
func Weekly(raw string) (*Schedule, error) {
|
||||
if err := validateWeeklySpec(raw); err != nil {
|
||||
return nil, xerrors.Errorf("validate weekly schedule: %w", err)
|
||||
@ -115,12 +116,12 @@ var tMax = t0.Add(168 * time.Hour)
|
||||
|
||||
// Min returns the minimum duration of the schedule.
|
||||
// This is calculated as follows:
|
||||
// - Let t(0) be a given point in time (1970-01-01T01:01:01Z00:00)
|
||||
// - Let t(max) be 168 hours after t(0).
|
||||
// - Let t(1) be the next scheduled time after t(0).
|
||||
// - Let t(n) be the next scheduled time after t(n-1).
|
||||
// - Then, the minimum duration of s d(min)
|
||||
// = min( t(n) - t(n-1) ∀ n ∈ N, t(n) < t(max) )
|
||||
// - Let t(0) be a given point in time (1970-01-01T01:01:01Z00:00)
|
||||
// - Let t(max) be 168 hours after t(0).
|
||||
// - Let t(1) be the next scheduled time after t(0).
|
||||
// - Let t(n) be the next scheduled time after t(n-1).
|
||||
// - Then, the minimum duration of s d(min)
|
||||
// = min( t(n) - t(n-1) ∀ n ∈ N, t(n) < t(max) )
|
||||
func (s Schedule) Min() time.Duration {
|
||||
durMin := tMax.Sub(t0)
|
||||
tPrev := s.Next(t0)
|
||||
|
@ -52,8 +52,10 @@ func Validate(ctx context.Context, signature string, options x509.VerifyOptions)
|
||||
}
|
||||
data, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
_ = res.Body.Close()
|
||||
return "", xerrors.Errorf("read body %q: %w", certURL, err)
|
||||
}
|
||||
_ = res.Body.Close()
|
||||
cert, err := x509.ParseCertificate(data)
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("parse certificate %q: %w", certURL, err)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/coder/coder/coderd/database/postgres"
|
||||
)
|
||||
|
||||
// nolint:tparallel,paralleltest
|
||||
func TestPubsub(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -22,10 +23,7 @@ func TestPubsub(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// nolint:paralleltest
|
||||
t.Run("Postgres", func(t *testing.T) {
|
||||
// postgres.Open() seems to be creating race conditions when run in parallel.
|
||||
// t.Parallel()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
@ -54,10 +52,7 @@ func TestPubsub(t *testing.T) {
|
||||
assert.Equal(t, string(message), data)
|
||||
})
|
||||
|
||||
// nolint:paralleltest
|
||||
t.Run("PostgresCloseCancel", func(t *testing.T) {
|
||||
// postgres.Open() seems to be creating race conditions when run in parallel.
|
||||
// t.Parallel()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
connectionURL, closePg, err := postgres.Open()
|
||||
|
@ -52,6 +52,7 @@ func TestTunnel(t *testing.T) {
|
||||
defer cancelTun()
|
||||
|
||||
server := http.Server{
|
||||
ReadHeaderTimeout: time.Minute,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Log("got request for", r.URL)
|
||||
// Going to use something _slightly_ exotic so that we can't accidentally get some
|
||||
@ -100,8 +101,8 @@ func TestTunnel(t *testing.T) {
|
||||
|
||||
// fakeTunnelServer is a fake version of the real dev tunnel server. It fakes 2 client interactions
|
||||
// that we want to test:
|
||||
// 1. Responding to a POST /tun from the client
|
||||
// 2. Sending an HTTP request down the wireguard connection
|
||||
// 1. Responding to a POST /tun from the client
|
||||
// 2. Sending an HTTP request down the wireguard connection
|
||||
//
|
||||
// Note that for 2, we don't implement a full proxy that accepts arbitrary requests, we just send
|
||||
// a test request over the Wireguard tunnel to make sure that we can listen. The proxy behavior is
|
||||
@ -229,5 +230,9 @@ func (f *fakeTunnelServer) requestHTTP() (*http.Response, error) {
|
||||
Transport: transport,
|
||||
Timeout: testutil.WaitLong,
|
||||
}
|
||||
return client.Get(fmt.Sprintf("http://[%s]:8090", clientIP))
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, fmt.Sprintf("http://[%s]:8090", clientIP), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.Do(req)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ func TestEntitlements(t *testing.T) {
|
||||
rw := httptest.NewRecorder()
|
||||
entitlements(rw, r)
|
||||
resp := rw.Result()
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
var result codersdk.Entitlements
|
||||
|
@ -99,7 +99,9 @@ func TestExtractUserRoles(t *testing.T) {
|
||||
})
|
||||
|
||||
rtr.ServeHTTP(rw, req)
|
||||
require.Equal(t, http.StatusOK, rw.Result().StatusCode)
|
||||
resp := rw.Result()
|
||||
defer resp.Body.Close()
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ func (*testOAuth2Provider) TokenSource(_ context.Context, _ *oauth2.Token) oauth
|
||||
return nil
|
||||
}
|
||||
|
||||
// nolint:bodyclose
|
||||
func TestOAuth2(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotSetup", func(t *testing.T) {
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
func TestPrometheus(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("All", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, chi.NewRouteContext()))
|
||||
res := chimw.NewWrapResponseWriter(httptest.NewRecorder(), 0)
|
||||
|
@ -26,7 +26,9 @@ func TestRateLimit(t *testing.T) {
|
||||
req := httptest.NewRequest("GET", "/", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
rtr.ServeHTTP(rec, req)
|
||||
return rec.Result().StatusCode == http.StatusTooManyRequests
|
||||
resp := rec.Result()
|
||||
defer resp.Body.Close()
|
||||
return resp.StatusCode == http.StatusTooManyRequests
|
||||
}, testutil.WaitShort, testutil.IntervalFast)
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -93,7 +94,7 @@ func TestPagination(t *testing.T) {
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
rw := httptest.NewRecorder()
|
||||
r, err := http.NewRequest("GET", "https://example.com", nil)
|
||||
r, err := http.NewRequestWithContext(context.Background(), "GET", "https://example.com", nil)
|
||||
require.NoError(t, err, "new request")
|
||||
|
||||
// Set query params
|
||||
|
@ -28,6 +28,7 @@ func TestProvisionerJobLogs_Unit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("QueryPubSubDupes", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
||||
// mDB := mocks.NewStore(t)
|
||||
fDB := databasefake.New()
|
||||
|
@ -54,6 +54,7 @@ type RegoAuthorizer struct {
|
||||
}
|
||||
|
||||
// Load the policy from policy.rego in this directory.
|
||||
//
|
||||
//go:embed policy.rego
|
||||
var policy string
|
||||
|
||||
|
@ -491,8 +491,8 @@ func TestAuthorizeDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestAuthorizeLevels ensures level overrides are acting appropriately
|
||||
//nolint:paralleltest
|
||||
func TestAuthorizeLevels(t *testing.T) {
|
||||
t.Parallel()
|
||||
defOrg := uuid.New()
|
||||
unusedID := uuid.New()
|
||||
|
||||
@ -638,6 +638,7 @@ func testAuthorize(t *testing.T, name string, subject subject, sets ...[]authTes
|
||||
for _, cases := range sets {
|
||||
for _, c := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, a := range c.actions {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
|
||||
t.Cleanup(cancel)
|
||||
|
@ -361,7 +361,9 @@ func ChangeRoleSet(from []string, to []string) (added []string, removed []string
|
||||
}
|
||||
|
||||
// roleName is a quick helper function to return
|
||||
// role_name:scopeID
|
||||
//
|
||||
// role_name:scopeID
|
||||
//
|
||||
// If no scopeID is required, only 'role_name' is returned
|
||||
func roleName(name string, orgID string) string {
|
||||
if orgID == "" {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// BenchmarkRBACFilter benchmarks the rbac.Filter method.
|
||||
//
|
||||
// go test -bench BenchmarkRBACFilter -benchmem -memprofile memprofile.out -cpuprofile profile.out
|
||||
func BenchmarkRBACFilter(b *testing.B) {
|
||||
orgs := []uuid.UUID{
|
||||
@ -392,6 +393,7 @@ func TestIsOrgRole(t *testing.T) {
|
||||
// nolint:paralleltest
|
||||
for _, c := range testCases {
|
||||
t.Run(c.RoleName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
orgID, ok := rbac.IsOrgRole(c.RoleName)
|
||||
require.Equal(t, c.OrgRole, ok, "match expected org role")
|
||||
require.Equal(t, c.OrgID, orgID, "match expected org id")
|
||||
|
@ -112,7 +112,7 @@ func TestListRoles(t *testing.T) {
|
||||
orgAdmin := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID, rbac.RoleOrgAdmin(admin.OrganizationID))
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
otherOrg, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
|
||||
Name: "other",
|
||||
|
@ -133,6 +133,7 @@ func (r *remoteReporter) reportSync(snapshot *Snapshot) {
|
||||
r.options.Logger.Debug(r.ctx, "submit", slog.Error(err))
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusAccepted {
|
||||
r.options.Logger.Debug(r.ctx, "bad response from telemetry server", slog.F("status", resp.StatusCode))
|
||||
return
|
||||
@ -261,6 +262,7 @@ func (r *remoteReporter) deployment() error {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("perform request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusAccepted {
|
||||
return xerrors.Errorf("update deployment: %w", err)
|
||||
}
|
||||
|
@ -818,7 +818,7 @@ func TestPaginatedTemplateVersions(t *testing.T) {
|
||||
|
||||
// This test takes longer than a long time.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong*2)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
// Populate database with template versions.
|
||||
total := 9
|
||||
|
@ -76,6 +76,7 @@ func TestUserAuthMethods(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// nolint:bodyclose
|
||||
func TestUserOAuth2Github(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("NotInAllowedOrganization", func(t *testing.T) {
|
||||
@ -281,6 +282,7 @@ func TestUserOAuth2Github(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// nolint:bodyclose
|
||||
func TestUserOIDC(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@ -456,7 +458,7 @@ func oauth2Callback(t *testing.T, client *codersdk.Client) *http.Response {
|
||||
state := "somestate"
|
||||
oauthURL, err := client.URL.Parse("/api/v2/users/oauth2/github/callback?code=asd&state=" + state)
|
||||
require.NoError(t, err)
|
||||
req, err := http.NewRequest("GET", oauthURL.String(), nil)
|
||||
req, err := http.NewRequestWithContext(context.Background(), "GET", oauthURL.String(), nil)
|
||||
require.NoError(t, err)
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: codersdk.OAuth2StateKey,
|
||||
@ -478,7 +480,7 @@ func oidcCallback(t *testing.T, client *codersdk.Client) *http.Response {
|
||||
state := "somestate"
|
||||
oauthURL, err := client.URL.Parse("/api/v2/users/oidc/callback?code=asd&state=" + state)
|
||||
require.NoError(t, err)
|
||||
req, err := http.NewRequest("GET", oauthURL.String(), nil)
|
||||
req, err := http.NewRequestWithContext(context.Background(), "GET", oauthURL.String(), nil)
|
||||
require.NoError(t, err)
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: codersdk.OAuth2StateKey,
|
||||
|
@ -477,7 +477,7 @@ func TestGrantSiteRoles(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
var err error
|
||||
|
||||
admin := coderdtest.New(t, nil)
|
||||
@ -734,7 +734,7 @@ func TestUsersFilter(t *testing.T) {
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
firstUser, err := client.User(ctx, codersdk.Me)
|
||||
require.NoError(t, err, "fetch me")
|
||||
@ -1075,7 +1075,7 @@ func TestSuspendedPagination(t *testing.T) {
|
||||
coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
me, err := client.User(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
@ -1121,7 +1121,7 @@ func TestPaginatedUsers(t *testing.T) {
|
||||
|
||||
// This test takes longer than a long time.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong*2)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
me, err := client.User(ctx, codersdk.Me)
|
||||
require.NoError(t, err)
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -27,6 +28,7 @@ func TestWorkspaceAppsProxyPath(t *testing.T) {
|
||||
ln, err := net.Listen("tcp", ":0")
|
||||
require.NoError(t, err)
|
||||
server := http.Server{
|
||||
ReadHeaderTimeout: time.Minute,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := r.Cookie(codersdk.SessionTokenKey)
|
||||
assert.ErrorIs(t, err, http.ErrNoCookie)
|
||||
|
@ -402,7 +402,7 @@ func TestWorkspaceFilter(t *testing.T) {
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
t.Cleanup(cancel)
|
||||
|
||||
users := make([]coderUser, 0)
|
||||
for i := 0; i < 10; i++ {
|
||||
|
@ -94,6 +94,7 @@ func TestCache(t *testing.T) {
|
||||
require.True(t, valid)
|
||||
|
||||
server := &http.Server{
|
||||
ReadHeaderTimeout: time.Minute,
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}),
|
||||
@ -131,8 +132,9 @@ func TestCache(t *testing.T) {
|
||||
proxy.Transport = conn.HTTPTransport()
|
||||
res := httptest.NewRecorder()
|
||||
proxy.ServeHTTP(res, req)
|
||||
res.Result().Body.Close()
|
||||
assert.Equal(t, http.StatusOK, res.Result().StatusCode)
|
||||
resp := res.Result()
|
||||
defer resp.Body.Close()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
Reference in New Issue
Block a user