1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
17 "git.arvados.org/arvados.git/lib/config"
18 "git.arvados.org/arvados.git/sdk/go/arvados"
19 "git.arvados.org/arvados.git/sdk/go/arvadostest"
20 "git.arvados.org/arvados.git/sdk/go/ctxlog"
21 "github.com/prometheus/client_golang/prometheus"
25 func Test(t *testing.T) {
29 var _ = check.Suite(&suite{})
35 func (s *suite) TearDownTest(c *check.C) {
36 arvados.NewClientFromEnv().RequestAndDecode(nil, "POST", "database/reset", nil, nil)
39 func (s *suite) SetUpTest(c *check.C) {
40 cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load()
41 c.Assert(err, check.IsNil)
42 cluster, err := cfg.GetCluster("")
43 c.Assert(err, check.IsNil)
44 cluster.Containers.CloudVMs.PollInterval = arvados.Duration(time.Second)
45 s.disp = newHandler(context.Background(), cluster, arvadostest.Dispatch1Token, prometheus.NewRegistry()).(*dispatcher)
46 s.disp.lsfcli.stubCommand = func(string, ...string) *exec.Cmd {
47 return exec.Command("bash", "-c", "echo >&2 unimplemented stub; false")
56 func (stub lsfstub) stubCommand(s *suite, c *check.C) func(prog string, args ...string) *exec.Cmd {
59 fakejobq := map[int]string{}
60 return func(prog string, args ...string) *exec.Cmd {
61 c.Logf("stubCommand: %q %q", prog, args)
62 if rand.Float64() < stub.errorRate {
63 return exec.Command("bash", "-c", "echo >&2 'stub random failure' && false")
65 if stub.sudoUser != "" && len(args) > 3 &&
69 args[2] == stub.sudoUser {
70 prog, args = args[3], args[4:]
74 defaultArgs := s.disp.Cluster.Containers.LSF.BsubArgumentsList
75 c.Assert(len(args) > len(defaultArgs), check.Equals, true)
76 c.Check(args[:len(defaultArgs)], check.DeepEquals, defaultArgs)
77 args = args[len(defaultArgs):]
79 c.Check(args[0], check.Equals, "-J")
81 case arvadostest.LockedContainerUUID:
82 c.Check(args, check.DeepEquals, []string{
83 "-J", arvadostest.LockedContainerUUID,
86 "-R", "rusage[mem=11701MB:tmp=0MB] span[hosts=1]"})
88 fakejobq[nextjobid] = args[1]
91 case arvadostest.QueuedContainerUUID:
92 c.Check(args, check.DeepEquals, []string{
93 "-J", arvadostest.QueuedContainerUUID,
96 "-R", "rusage[mem=11701MB:tmp=45777MB] span[hosts=1]"})
98 fakejobq[nextjobid] = args[1]
102 c.Errorf("unexpected uuid passed to bsub: args %q", args)
103 return exec.Command("false")
105 return exec.Command("echo", "submitted job")
107 c.Check(args, check.DeepEquals, []string{"-u", "all", "-noheader", "-o", "jobid stat job_name:30"})
109 for jobid, uuid := range fakejobq {
110 out += fmt.Sprintf(`%d %s %s\n`, jobid, "RUN", uuid)
112 c.Logf("bjobs out: %q", out)
113 return exec.Command("printf", out)
115 killid, _ := strconv.Atoi(args[0])
116 if uuid, ok := fakejobq[killid]; !ok {
117 return exec.Command("bash", "-c", fmt.Sprintf("printf >&2 'Job <%d>: No matching job found\n'", killid))
118 } else if uuid == "" {
119 return exec.Command("bash", "-c", fmt.Sprintf("printf >&2 'Job <%d>: Job has already finished\n'", killid))
122 time.Sleep(time.Millisecond)
124 delete(fakejobq, killid)
127 return exec.Command("bash", "-c", fmt.Sprintf("printf 'Job <%d> is being terminated\n'", killid))
130 return exec.Command("bash", "-c", fmt.Sprintf("echo >&2 'stub: command not found: %+q'", prog))
135 func (s *suite) TestSubmit(c *check.C) {
136 s.disp.lsfcli.stubCommand = lsfstub{
138 sudoUser: s.disp.Cluster.Containers.LSF.BsubSudoUser,
141 deadline := time.Now().Add(20 * time.Second)
142 for range time.NewTicker(time.Second).C {
143 if time.Now().After(deadline) {
147 // "queuedcontainer" should be running
148 if _, ok := s.disp.lsfqueue.JobID(arvadostest.QueuedContainerUUID); !ok {
151 // "lockedcontainer" should be cancelled because it
152 // has priority 0 (no matching container requests)
153 if _, ok := s.disp.lsfqueue.JobID(arvadostest.LockedContainerUUID); ok {
156 var ctr arvados.Container
157 if err := s.disp.arvDispatcher.Arv.Get("containers", arvadostest.LockedContainerUUID, nil, &ctr); err != nil {
158 c.Logf("error getting container state for %s: %s", arvadostest.LockedContainerUUID, err)
161 if ctr.State != arvados.ContainerStateQueued {
162 c.Logf("LockedContainer is not in the LSF queue but its arvados record has not been updated to state==Queued (state is %q)", ctr.State)
165 c.Log("reached desired state")