package api import ( "os" "path/filepath" "sync" "testing" ) func TestProfileQuotaReplacement(t *testing.T) { if os.Geteuid() != 0 { t.Skip("requires chown") } a, i, home := configTestAPI(t, false) profile := filepath.Join(home, "profiles/web/cordis.patch.yml") if err := os.MkdirAll(filepath.Dir(profile), 0700); err != nil { t.Fatal(err) } configWrite(t, profile, "foo: old") if _, err := a.s.DB.Exec("UPDATE users SET quota=8 WHERE id=?", i.UID); err != nil { t.Fatal(err) } for _, tc := range []struct { body string code int }{ {`{"content":"foo: biggg"}`, 413}, {`{"content":"foo: new"}`, 200}, {`{"content":"foo: x"}`, 200}, } { w := configCall(a, i, "PUT", "profile", tc.body) if w.Code != tc.code { t.Fatalf("%d %s", w.Code, w.Body.String()) } } data, err := os.ReadFile(profile) if err != nil || string(data) != "foo: x" { t.Fatalf("%q %v", data, err) } } func TestSnapshotQuotaIncludesResourcesAndExistingSnapshots(t *testing.T) { a, i, home := configTestAPI(t, false) configWrite(t, filepath.Join(home, "state"), "1234") if err := os.MkdirAll(filepath.Join(filepath.Dir(home), "pre-restore-old"), 0700); err != nil { t.Fatal(err) } configWrite(t, filepath.Join(filepath.Dir(home), "pre-restore-old/state"), "1234") root, err := os.OpenRoot(filepath.Dir(home)) if err != nil { t.Fatal(err) } defer root.Close() if _, err = a.s.DB.Exec("UPDATE users SET quota=15 WHERE id=?", i.UID); err != nil { t.Fatal(err) } if _, err = a.quotaSnapshot(i.UID, root, 4); err == nil { t.Fatal("resource bytes omitted") } if size, err := a.quotaSnapshot(i.UID, root, 3); err != nil || size != 4 { t.Fatalf("size=%d err=%v", size, err) } if _, err := root.Lstat("pre-restore-old/state"); err != nil { t.Fatal("existing snapshot changed") } } func TestQuotaSerializedWriters(t *testing.T) { a, i, home := configTestAPI(t, false) if _, err := a.s.DB.Exec("UPDATE users SET quota=4 WHERE id=?", i.UID); err != nil { t.Fatal(err) } var wg sync.WaitGroup accepted := 0 for _, name := range []string{"one", "two"} { wg.Add(1) go func() { defer wg.Done() user := a.userLocks.Acquire(i.UID) defer user.Release() if a.quotaGrowth(i.UID, 4) == nil { if err := os.WriteFile(filepath.Join(home, name), []byte("1234"), 0600); err != nil { t.Error(err) return } accepted++ } }() } wg.Wait() if accepted != 1 { t.Fatalf("accepted %d writes", accepted) } }