// Copyright (c) 2021 Gitpod GmbH. All rights reserved. // Licensed under the GNU Affero General Public License (AGPL). // See License.AGPL.txt in the project root for license information. package quota import ( "fmt" "sort" "strings" "testing" "github.com/google/go-cmp/cmp" ) func TestGetUsedProjectIDs(t *testing.T) { type Expectation struct { ProjectIDs []int Error string } tests := []struct { Name string Input string InputErr error Expectation Expectation }{ { Name: "no projects", Input: "", }, { Name: "single project", Input: "#0 4 0 0 00 [------]", Expectation: Expectation{ ProjectIDs: []int{0}, }, }, { Name: "multiple projects none used", Input: "#0 0 0 0 00 [------]\n#100 0 5M 5M 00 [------]\n#200 0 10M 10M 00 [------]", }, { Name: "multiple projects in use", Input: "#0 0 0 0 00 [------]\n#100 4 5M 5M 00 [------]\n#200 1 10M 10M 00 [------]", Expectation: Expectation{ ProjectIDs: []int{100, 200}, }, }, { Name: "exec failure", InputErr: fmt.Errorf("exec failed"), Expectation: Expectation{ Error: "exec failed", }, }, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { xfs := &XFS{ exec: func(dir, command string) (output string, err error) { return test.Input, test.InputErr }, } var ( act Expectation err error ) act.ProjectIDs, err = xfs.getUsedProjectIDs() if err != nil { act.Error = err.Error() } if diff := cmp.Diff(test.Expectation, act); diff != "" { t.Errorf("unexpected getUsedProjectIDs (-want +got):\n%s", diff) } }) } } func TestSetQuota(t *testing.T) { type Expectation struct { ProjectID int ProjectIDs []int Execs []string Error string } tests := []struct { Name string Size Size IsHard bool ExecErr func(cmd string) error ProjectIDs []int Expectation Expectation }{ { Name: "happpy path", Size: 100 * Kilobyte, IsHard: true, Expectation: Expectation{ ProjectID: 1000, ProjectIDs: []int{1000}, Execs: []string{ "project -s -d 1 -p /foo 1000", "limit -p bhard=102400 1000", }, }, }, { Name: "with soft limit", Size: 100 * Kilobyte, IsHard: false, Expectation: Expectation{ ProjectID: 1000, ProjectIDs: []int{1000}, Execs: []string{ "project -s -d 1 -p /foo 1000", "limit -p bsoft=102400 1000", }, }, }, { Name: "with other prj", Size: 100 * Kilobyte, IsHard: true, ProjectIDs: []int{1000}, Expectation: Expectation{ ProjectID: 1001, ProjectIDs: []int{1000, 1001}, Execs: []string{ "project -s -d 1 -p /foo 1001", "limit -p bhard=102400 1001", }, }, }, { Name: "prj creation failure", Size: 100 * Kilobyte, IsHard: true, ExecErr: func(cmd string) error { if strings.Contains(cmd, "project") { return fmt.Errorf("failed to create project") } return nil }, Expectation: Expectation{ ProjectID: 0, Execs: []string{ "project -s -d 1 -p /foo 1000", }, Error: "failed to create project", }, }, } for _, test := range tests { t.Run(test.Name, func(t *testing.T) { var ( act Expectation err error ) xfs := &XFS{ exec: func(dir, command string) (output string, err error) { act.Execs = append(act.Execs, command) if test.ExecErr != nil { return "", test.ExecErr(command) } return "", nil }, projectIDs: make(map[int]struct{}), Dir: "/", } for _, prjid := range test.ProjectIDs { xfs.projectIDs[prjid] = struct{}{} } act.ProjectID, err = xfs.SetQuota("/foo", test.Size, test.IsHard) if err != nil { act.Error = err.Error() } for p := range xfs.projectIDs { act.ProjectIDs = append(act.ProjectIDs, p) } sort.Ints(act.ProjectIDs) if diff := cmp.Diff(test.Expectation, act); diff != "" { t.Errorf("unexpected SetQuota (-want +got):\n%s", diff) } }) } }