summaryrefslogtreecommitdiff
path: root/requests/requests_workerchange_test.go
blob: 1ce2eb8834bf1b0e78ea73dc8f4e91d2032f3c73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 */

package requests

import (
	"errors"
	"time"

	. "git.tizen.org/tools/boruta"
	"git.tizen.org/tools/boruta/workers"

	gomock "github.com/golang/mock/gomock"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Requests as WorkerChange", func() {
	var ctrl *gomock.Controller
	var wm *MockWorkersManager
	var jm *MockJobsManager
	var R *ReqsCollection
	testErr := errors.New("Test Error")
	testWorker := WorkerUUID("Test Worker UUID")
	noWorker := WorkerUUID("")
	testCapabilities := Capabilities{"key": "value"}
	testPriority := (HiPrio + LoPrio) / 2
	testUser := UserInfo{Groups: []Group{"Test Group"}}
	now := time.Now()
	tomorrow := now.AddDate(0, 0, 1)
	trigger := make(chan int, 1)

	setTrigger := func(val int) {
		trigger <- val
	}
	eventuallyTrigger := func(val int) {
		EventuallyWithOffset(1, trigger).Should(Receive(Equal(val)))
	}
	eventuallyState := func(reqid ReqID, state ReqState) {
		EventuallyWithOffset(1, func() ReqState {
			info, err := R.GetRequestInfo(reqid)
			ExpectWithOffset(1, err).NotTo(HaveOccurred())
			ExpectWithOffset(1, info).NotTo(BeNil())
			return info.State
		}).Should(Equal(state))
	}

	BeforeEach(func() {
		ctrl = gomock.NewController(GinkgoT())
		wm = NewMockWorkersManager(ctrl)
		jm = NewMockJobsManager(ctrl)
		wm.EXPECT().SetChangeListener(gomock.Any())
		R = NewRequestQueue(wm, jm)
	})
	AfterEach(func() {
		R.Finish()
		ctrl.Finish()
	})

	Describe("OnWorkerIdle", func() {
		It("ValidMatcher should do nothing if there are no waiting requests", func() {
			R.OnWorkerIdle(testWorker)
		})
		It("ValidMatcher should try matching request", func() {
			// Add Request. Use trigger to wait for ValidMatcher goroutine to match worker.
			wm.EXPECT().TakeBestMatchingWorker(testUser.Groups, testCapabilities).Return(noWorker, testErr).Do(func(Groups, Capabilities) {
				setTrigger(1)
			})
			reqid, err := R.NewRequest(testCapabilities, testPriority, testUser, now, tomorrow)
			Expect(err).NotTo(HaveOccurred())
			Expect(reqid).NotTo(BeZero())
			eventuallyTrigger(1)

			// Test. Use trigger to wait for ValidMatcher goroutine to match worker.
			wm.EXPECT().TakeBestMatchingWorker(testUser.Groups, testCapabilities).Return(noWorker, testErr).Do(func(Groups, Capabilities) {
				setTrigger(2)
			})
			R.OnWorkerIdle(testWorker)
			eventuallyTrigger(2)
		})
	})
	Describe("OnWorkerFail", func() {
		It("should panic if jobs.Get fails", func() {
			jm.EXPECT().Get(testWorker).Return(nil, testErr)
			Expect(func() {
				R.OnWorkerFail(testWorker)
			}).To(Panic())
		})
		It("should panic if failing worker was processing unknown Job", func() {
			noReq := ReqID(0)
			job := workers.Job{Req: noReq}
			jm.EXPECT().Get(testWorker).Return(&job, nil)
			Expect(func() {
				R.OnWorkerFail(testWorker)
			}).To(Panic())
		})
		It("should set request to FAILED state if call succeeds", func() {
			// Add Request. Use trigger to wait for ValidMatcher goroutine to match worker.
			wm.EXPECT().TakeBestMatchingWorker(testUser.Groups, testCapabilities).Return(noWorker, testErr).Do(func(Groups, Capabilities) {
				setTrigger(3)
			})
			reqid, err := R.NewRequest(testCapabilities, testPriority, testUser, now, tomorrow)
			Expect(err).NotTo(HaveOccurred())
			Expect(reqid).NotTo(BeZero())
			eventuallyTrigger(3)

			// Test.
			job := workers.Job{Req: reqid}
			jm.EXPECT().Get(testWorker).Return(&job, nil)
			jm.EXPECT().Finish(testWorker)
			R.OnWorkerFail(testWorker)
			eventuallyState(reqid, FAILED)
		})
	})
})