taskflow 5.7.0__py3-none-any.whl → 5.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
taskflow/test.py CHANGED
@@ -19,9 +19,7 @@ from unittest import mock
19
19
  import fixtures
20
20
  from oslotest import base
21
21
 
22
- from testtools import compat
23
22
  from testtools import matchers
24
- from testtools import testcase
25
23
 
26
24
  from taskflow import exceptions
27
25
  from taskflow.tests import fixtures as taskflow_fixtures
@@ -122,30 +120,6 @@ class TestCase(base.BaseTestCase):
122
120
 
123
121
  self.assertRaises(exc_class, access_func)
124
122
 
125
- def assertRaisesRegex(self, exc_class, pattern, callable_obj,
126
- *args, **kwargs):
127
- # TODO(harlowja): submit a pull/review request to testtools to add
128
- # this method to there codebase instead of having it exist in ours
129
- # since it really doesn't belong here.
130
-
131
- class ReRaiseOtherTypes(object):
132
- def match(self, matchee):
133
- if not issubclass(matchee[0], exc_class):
134
- compat.reraise(*matchee)
135
-
136
- class CaptureMatchee(object):
137
- def match(self, matchee):
138
- self.matchee = matchee[1]
139
-
140
- capture = CaptureMatchee()
141
- matcher = matchers.Raises(matchers.MatchesAll(ReRaiseOtherTypes(),
142
- matchers.MatchesException(exc_class,
143
- pattern),
144
- capture))
145
- our_callable = testcase.Nullary(callable_obj, *args, **kwargs)
146
- self.assertThat(our_callable, matcher)
147
- return capture.matchee
148
-
149
123
  def assertGreater(self, first, second):
150
124
  matcher = matchers.GreaterThan(first)
151
125
  self.assertThat(second, matcher)
@@ -19,7 +19,6 @@ import testtools
19
19
 
20
20
  from taskflow.engines.action_engine import engine
21
21
  from taskflow.engines.action_engine import executor
22
- from taskflow.engines.action_engine import process_executor
23
22
  from taskflow.patterns import linear_flow as lf
24
23
  from taskflow.persistence import backends
25
24
  from taskflow import test
@@ -27,6 +26,11 @@ from taskflow.tests import utils
27
26
  from taskflow.utils import eventlet_utils as eu
28
27
  from taskflow.utils import persistence_utils as pu
29
28
 
29
+ try:
30
+ from taskflow.engines.action_engine import process_executor as pe
31
+ except ImportError:
32
+ pe = None
33
+
30
34
 
31
35
  class ParallelCreationTest(test.TestCase):
32
36
  @staticmethod
@@ -44,11 +48,12 @@ class ParallelCreationTest(test.TestCase):
44
48
  self.assertIsInstance(eng._task_executor,
45
49
  executor.ParallelThreadTaskExecutor)
46
50
 
51
+ @testtools.skipIf(pe is None, 'process_executor is not available')
47
52
  def test_process_string_creation(self):
48
53
  for s in ['process', 'processes']:
49
54
  eng = self._create_engine(executor=s)
50
55
  self.assertIsInstance(eng._task_executor,
51
- process_executor.ParallelProcessTaskExecutor)
56
+ pe.ParallelProcessTaskExecutor)
52
57
 
53
58
  def test_thread_executor_creation(self):
54
59
  with futurist.ThreadPoolExecutor(1) as e:
@@ -56,11 +61,12 @@ class ParallelCreationTest(test.TestCase):
56
61
  self.assertIsInstance(eng._task_executor,
57
62
  executor.ParallelThreadTaskExecutor)
58
63
 
64
+ @testtools.skipIf(pe is None, 'process_executor is not available')
59
65
  def test_process_executor_creation(self):
60
66
  with futurist.ProcessPoolExecutor(1) as e:
61
67
  eng = self._create_engine(executor=e)
62
68
  self.assertIsInstance(eng._task_executor,
63
- process_executor.ParallelProcessTaskExecutor)
69
+ pe.ParallelProcessTaskExecutor)
64
70
 
65
71
  @testtools.skipIf(not eu.EVENTLET_AVAILABLE, 'eventlet is not available')
66
72
  def test_green_executor_creation(self):
@@ -13,19 +13,26 @@
13
13
  # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
14
  # License for the specific language governing permissions and limitations
15
15
  # under the License.
16
-
17
- import asyncore
18
16
  import errno
19
17
  import socket
20
18
  import threading
21
19
 
22
- from taskflow.engines.action_engine import process_executor as pu
20
+ import testtools
21
+
23
22
  from taskflow import task
24
23
  from taskflow import test
25
24
  from taskflow.test import mock
26
25
  from taskflow.tests import utils as test_utils
27
26
 
27
+ try:
28
+ import asyncore
29
+ from taskflow.engines.action_engine import process_executor as pe
30
+ except ImportError:
31
+ asyncore = None
32
+ pe = None
33
+
28
34
 
35
+ @testtools.skipIf(asyncore is None, 'process_executor is not available')
29
36
  class ProcessExecutorHelpersTest(test.TestCase):
30
37
  def test_reader(self):
31
38
  capture_buf = []
@@ -33,8 +40,8 @@ class ProcessExecutorHelpersTest(test.TestCase):
33
40
  def do_capture(identity, message_capture_func):
34
41
  capture_buf.append(message_capture_func())
35
42
 
36
- r = pu.Reader(b"secret", do_capture)
37
- for data in pu._encode_message(b"secret", ['hi'], b'me'):
43
+ r = pe.Reader(b"secret", do_capture)
44
+ for data in pe._encode_message(b"secret", ['hi'], b'me'):
38
45
  self.assertEqual(len(data), r.bytes_needed)
39
46
  r.feed(data)
40
47
 
@@ -42,9 +49,9 @@ class ProcessExecutorHelpersTest(test.TestCase):
42
49
  self.assertEqual(['hi'], capture_buf[0])
43
50
 
44
51
  def test_bad_hmac_reader(self):
45
- r = pu.Reader(b"secret-2", lambda ident, capture_func: capture_func())
46
- in_data = b"".join(pu._encode_message(b"secret", ['hi'], b'me'))
47
- self.assertRaises(pu.BadHmacValueError, r.feed, in_data)
52
+ r = pe.Reader(b"secret-2", lambda ident, capture_func: capture_func())
53
+ in_data = b"".join(pe._encode_message(b"secret", ['hi'], b'me'))
54
+ self.assertRaises(pe.BadHmacValueError, r.feed, in_data)
48
55
 
49
56
  @mock.patch("socket.socket")
50
57
  def test_no_connect_channel(self, mock_socket_factory):
@@ -52,7 +59,7 @@ class ProcessExecutorHelpersTest(test.TestCase):
52
59
  mock_socket_factory.return_value = mock_sock
53
60
  mock_sock.connect.side_effect = socket.error(errno.ECONNREFUSED,
54
61
  'broken')
55
- c = pu.Channel(2222, b"me", b"secret")
62
+ c = pe.Channel(2222, b"me", b"secret")
56
63
  self.assertRaises(socket.error, c.send, "hi")
57
64
  self.assertTrue(c.dead)
58
65
  self.assertTrue(mock_sock.close.called)
@@ -65,7 +72,7 @@ class ProcessExecutorHelpersTest(test.TestCase):
65
72
  task.EVENT_UPDATE_PROGRESS,
66
73
  lambda _event_type, details: details_capture.append(details))
67
74
 
68
- d = pu.Dispatcher({}, b'secret', b'server-josh')
75
+ d = pe.Dispatcher({}, b'secret', b'server-josh')
69
76
  d.setup()
70
77
  d.targets[b'child-josh'] = t
71
78
 
@@ -73,7 +80,7 @@ class ProcessExecutorHelpersTest(test.TestCase):
73
80
  s.start()
74
81
  self.addCleanup(s.join)
75
82
 
76
- c = pu.Channel(d.port, b'child-josh', b'secret')
83
+ c = pe.Channel(d.port, b'child-josh', b'secret')
77
84
  self.addCleanup(c.close)
78
85
 
79
86
  send_what = [
@@ -87,7 +94,7 @@ class ProcessExecutorHelpersTest(test.TestCase):
87
94
  {'progress': 0.8},
88
95
  {'progress': 0.9},
89
96
  ]
90
- e_s = pu.EventSender(c)
97
+ e_s = pe.EventSender(c)
91
98
  for details in send_what:
92
99
  e_s(task.EVENT_UPDATE_PROGRESS, details)
93
100
 
@@ -0,0 +1,421 @@
1
+ # Copyright (C) Red Hat
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ from unittest import mock
16
+
17
+ from oslo_serialization import jsonutils
18
+ from oslo_utils import uuidutils
19
+ import testtools
20
+
21
+ from taskflow import exceptions as exc
22
+ from taskflow.jobs.backends import impl_etcd
23
+ from taskflow.jobs import base as jobs_base
24
+ from taskflow import test
25
+ from taskflow.tests.unit.jobs import base
26
+ from taskflow.tests import utils as test_utils
27
+
28
+ ETCD_AVAILABLE = test_utils.etcd_available()
29
+
30
+
31
+ class EtcdJobBoardMixin:
32
+ def create_board(self, conf=None, persistence=None):
33
+ self.path = f"test-{uuidutils.generate_uuid()}"
34
+ board_conf = {
35
+ "path": self.path,
36
+ }
37
+ if conf:
38
+ board_conf.update(conf)
39
+ board = impl_etcd.EtcdJobBoard("etcd", board_conf,
40
+ persistence=persistence)
41
+ return board._client, board
42
+
43
+
44
+ class MockedEtcdJobBoard(test.TestCase, EtcdJobBoardMixin):
45
+
46
+ def test_create_board(self):
47
+ _, jobboard = self.create_board()
48
+ self.assertEqual(f"/taskflow/jobs/{self.path}", jobboard._root_path)
49
+
50
+ _, jobboard = self.create_board({"path": "/testpath"})
51
+ self.assertEqual("/taskflow/jobs/testpath", jobboard._root_path)
52
+
53
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard.incr")
54
+ @mock.patch("threading.Condition")
55
+ @mock.patch("oslo_utils.uuidutils.generate_uuid")
56
+ @mock.patch("oslo_utils.timeutils.utcnow")
57
+ def test_post(self,
58
+ mock_utcnow: mock.Mock,
59
+ mock_generated_uuid: mock.Mock,
60
+ mock_cond: mock.Mock,
61
+ mock_incr: mock.Mock):
62
+ mock_incr.return_value = 12
63
+ mock_generated_uuid.return_value = "uuid1"
64
+ mock_utcnow.return_value = "utcnow1"
65
+
66
+ mock_book = mock.Mock()
67
+ mock_book.name = "book1_name"
68
+ mock_book.uuid = "book1_uuid"
69
+ mock_details = mock.Mock()
70
+
71
+ _, jobboard = self.create_board()
72
+ jobboard._client = mock.Mock()
73
+ job = jobboard.post("post1", book=mock_book,
74
+ details=mock_details,
75
+ priority=jobs_base.JobPriority.NORMAL)
76
+
77
+ expected_key = (
78
+ f"/taskflow/jobs/{self.path}/job12")
79
+ expected_data_key = expected_key + jobboard.DATA_POSTFIX
80
+ expected_book_data = {
81
+ "name": "book1_name",
82
+ "uuid": "book1_uuid"
83
+ }
84
+ expected_job_posting = {
85
+ "uuid": "uuid1",
86
+ "name": "post1",
87
+ "priority": "NORMAL",
88
+ "created_on": "utcnow1",
89
+ "details": mock_details,
90
+ "book": expected_book_data,
91
+ "sequence": 12,
92
+ }
93
+
94
+ mock_incr.assert_called_with(f"/taskflow/jobs/{self.path}/sequence")
95
+
96
+ jobboard._client.create.assert_called_with(
97
+ expected_data_key, jsonutils.dumps(expected_job_posting))
98
+
99
+ self.assertEqual("post1", job.name)
100
+ self.assertEqual(expected_key, job.key)
101
+ self.assertEqual(mock_details, job.details)
102
+ self.assertEqual(mock_book, job.book)
103
+ self.assertEqual(expected_book_data, job._book_data)
104
+ self.assertEqual(jobs_base.JobPriority.NORMAL, job.priority)
105
+ self.assertEqual(12, job.sequence)
106
+
107
+ self.assertEqual(1, len(jobboard._job_cache))
108
+ self.assertEqual(job, jobboard._job_cache[expected_key])
109
+
110
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
111
+ "set_last_modified")
112
+ def test_claim(self, mock_set_last_modified):
113
+ who = "owner1"
114
+ lease_id = uuidutils.generate_uuid()
115
+
116
+ _, jobboard = self.create_board(conf={"ttl": 37})
117
+ jobboard._client = mock.Mock()
118
+
119
+ mock_lease = mock.Mock(id=lease_id)
120
+ jobboard._client.lease.return_value = mock_lease
121
+ jobboard._client.create.return_value = True
122
+ jobboard._client.get.return_value = [mock.Mock()]
123
+
124
+ job = impl_etcd.EtcdJob(jobboard,
125
+ "job7",
126
+ jobboard._client,
127
+ f"/taskflow/jobs/{self.path}/job7",
128
+ uuid=uuidutils.generate_uuid(),
129
+ details=mock.Mock(),
130
+ backend="etcd",
131
+ book=mock.Mock(),
132
+ book_data=mock.Mock(),
133
+ priority=jobs_base.JobPriority.NORMAL,
134
+ sequence=7,
135
+ created_on="date")
136
+
137
+ jobboard.claim(job, who)
138
+
139
+ jobboard._client.lease.assert_called_once_with(ttl=37)
140
+
141
+ jobboard._client.create.assert_called_once_with(
142
+ f"{job.key}{jobboard.LOCK_POSTFIX}",
143
+ jsonutils.dumps({"owner": who,
144
+ "lease_id": lease_id}),
145
+ lease=mock_lease)
146
+
147
+ jobboard._client.get.assert_called_once_with(
148
+ job.key + jobboard.DATA_POSTFIX)
149
+ mock_lease.revoke.assert_not_called()
150
+
151
+ mock_set_last_modified.assert_called_once_with(job)
152
+
153
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
154
+ "set_last_modified")
155
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
156
+ "find_owner")
157
+ def test_claim_already_claimed(self, mock_find_owner,
158
+ mock_set_last_modified):
159
+ who = "owner1"
160
+ lease_id = uuidutils.generate_uuid()
161
+
162
+ mock_find_owner.return_value = who
163
+
164
+ _, jobboard = self.create_board({"ttl": 37})
165
+ jobboard._client = mock.Mock()
166
+
167
+ mock_lease = mock.Mock(id=lease_id)
168
+ jobboard._client.lease.return_value = mock_lease
169
+ jobboard._client.create.return_value = False
170
+ jobboard._client.get.return_value = []
171
+
172
+ job = impl_etcd.EtcdJob(jobboard,
173
+ "job7",
174
+ jobboard._client,
175
+ f"/taskflow/jobs/{self.path}/job7",
176
+ uuid=uuidutils.generate_uuid(),
177
+ details=mock.Mock(),
178
+ backend="etcd",
179
+ book=mock.Mock(),
180
+ book_data=mock.Mock(),
181
+ priority=jobs_base.JobPriority.NORMAL,
182
+ sequence=7,
183
+ created_on="date")
184
+
185
+ self.assertRaisesRegex(exc.UnclaimableJob, "already claimed by",
186
+ jobboard.claim, job, who)
187
+
188
+ jobboard._client.lease.assert_called_once_with(ttl=37)
189
+
190
+ jobboard._client.create.assert_called_once_with(
191
+ f"{job.key}{jobboard.LOCK_POSTFIX}",
192
+ jsonutils.dumps({"owner": who,
193
+ "lease_id": lease_id}),
194
+ lease=mock_lease)
195
+
196
+ mock_lease.revoke.assert_called_once()
197
+
198
+ mock_set_last_modified.assert_not_called()
199
+
200
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
201
+ "set_last_modified")
202
+ def test_claim_deleted(self, mock_set_last_modified):
203
+ who = "owner1"
204
+ lease_id = uuidutils.generate_uuid()
205
+
206
+ _, jobboard = self.create_board({"ttl": 37})
207
+ jobboard._client = mock.Mock()
208
+
209
+ mock_lease = mock.Mock(id=lease_id)
210
+ jobboard._client.lease.return_value = mock_lease
211
+ jobboard._client.create.return_value = True
212
+ jobboard._client.get.return_value = []
213
+
214
+ job = impl_etcd.EtcdJob(jobboard,
215
+ "job7",
216
+ jobboard._client,
217
+ f"/taskflow/jobs/{self.path}/job7",
218
+ uuid=uuidutils.generate_uuid(),
219
+ details=mock.Mock(),
220
+ backend="etcd",
221
+ book=mock.Mock(),
222
+ book_data=mock.Mock(),
223
+ priority=jobs_base.JobPriority.NORMAL,
224
+ sequence=7,
225
+ created_on="date")
226
+
227
+ self.assertRaisesRegex(exc.UnclaimableJob, "already deleted",
228
+ jobboard.claim, job, who)
229
+
230
+ jobboard._client.lease.assert_called_once_with(ttl=37)
231
+
232
+ jobboard._client.create.assert_called_once_with(
233
+ f"{job.key}{jobboard.LOCK_POSTFIX}",
234
+ jsonutils.dumps({"owner": who,
235
+ "lease_id": lease_id}),
236
+ lease=mock_lease)
237
+
238
+ jobboard._client.get.assert_called_once_with(
239
+ job.key + jobboard.DATA_POSTFIX)
240
+ mock_lease.revoke.assert_called_once()
241
+
242
+ mock_set_last_modified.assert_not_called()
243
+
244
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
245
+ "get_owner_and_data")
246
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
247
+ "_remove_job_from_cache")
248
+ def test_consume(self, mock__remove_job_from_cache,
249
+ mock_get_owner_and_data):
250
+ mock_get_owner_and_data.return_value = ["owner1", mock.Mock()]
251
+
252
+ _, jobboard = self.create_board()
253
+ jobboard._client = mock.Mock()
254
+
255
+ job = impl_etcd.EtcdJob(jobboard,
256
+ "job7",
257
+ jobboard._client,
258
+ f"/taskflow/jobs/{self.path}/job7")
259
+ jobboard.consume(job, "owner1")
260
+
261
+ jobboard._client.delete_prefix.assert_called_once_with(job.key + ".")
262
+ mock__remove_job_from_cache.assert_called_once_with(job.key)
263
+
264
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
265
+ "get_owner_and_data")
266
+ def test_consume_bad_owner(self, mock_get_owner_and_data):
267
+ mock_get_owner_and_data.return_value = ["owner2", mock.Mock()]
268
+
269
+ _, jobboard = self.create_board()
270
+ jobboard._client = mock.Mock()
271
+
272
+ job = impl_etcd.EtcdJob(jobboard,
273
+ "job7",
274
+ jobboard._client,
275
+ f"/taskflow/jobs/{self.path}/job7")
276
+ self.assertRaisesRegex(exc.JobFailure, "which is not owned",
277
+ jobboard.consume, job, "owner1")
278
+
279
+ jobboard._client.delete_prefix.assert_not_called()
280
+
281
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
282
+ "get_owner_and_data")
283
+ def test_abandon(self, mock_get_owner_and_data):
284
+ mock_get_owner_and_data.return_value = ["owner1", mock.Mock()]
285
+
286
+ _, jobboard = self.create_board()
287
+ jobboard._client = mock.Mock()
288
+
289
+ job = impl_etcd.EtcdJob(jobboard,
290
+ "job7",
291
+ jobboard._client,
292
+ f"/taskflow/jobs/{self.path}/job7")
293
+ jobboard.abandon(job, "owner1")
294
+
295
+ jobboard._client.delete.assert_called_once_with(
296
+ f"{job.key}{jobboard.LOCK_POSTFIX}")
297
+
298
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
299
+ "get_owner_and_data")
300
+ def test_abandon_bad_owner(self, mock_get_owner_and_data):
301
+ mock_get_owner_and_data.return_value = ["owner2", mock.Mock()]
302
+
303
+ _, jobboard = self.create_board()
304
+ jobboard._client = mock.Mock()
305
+
306
+ job = impl_etcd.EtcdJob(jobboard,
307
+ "job7",
308
+ jobboard._client,
309
+ f"/taskflow/jobs/{self.path}/job7")
310
+ self.assertRaisesRegex(exc.JobFailure, "which is not owned",
311
+ jobboard.abandon, job, "owner1")
312
+
313
+ jobboard._client.delete.assert_not_called()
314
+
315
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
316
+ "get_owner_and_data")
317
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
318
+ "_remove_job_from_cache")
319
+ def test_trash(self, mock__remove_job_from_cache,
320
+ mock_get_owner_and_data):
321
+ mock_get_owner_and_data.return_value = ["owner1", mock.Mock()]
322
+
323
+ _, jobboard = self.create_board()
324
+ jobboard._client = mock.Mock()
325
+
326
+ job = impl_etcd.EtcdJob(jobboard,
327
+ "job7",
328
+ jobboard._client,
329
+ f"/taskflow/jobs/{self.path}/job7")
330
+ jobboard.trash(job, "owner1")
331
+
332
+ jobboard._client.create.assert_called_once_with(
333
+ f"/taskflow/.trash/{self.path}/job7", mock.ANY)
334
+ jobboard._client.delete_prefix.assert_called_once_with(job.key + ".")
335
+ mock__remove_job_from_cache.assert_called_once_with(job.key)
336
+
337
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
338
+ "get_owner_and_data")
339
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
340
+ "_remove_job_from_cache")
341
+ def test_trash_bad_owner(self, mock__remove_job_from_cache,
342
+ mock_get_owner_and_data):
343
+ mock_get_owner_and_data.return_value = ["owner2", mock.Mock()]
344
+
345
+ _, jobboard = self.create_board()
346
+ jobboard._client = mock.Mock()
347
+
348
+ job = impl_etcd.EtcdJob(jobboard,
349
+ "job7",
350
+ jobboard._client,
351
+ f"/taskflow/jobs/{self.path}/job7")
352
+ self.assertRaisesRegex(exc.JobFailure, "which is not owned",
353
+ jobboard.trash, job, "owner1")
354
+
355
+ jobboard._client.create.assert_not_called()
356
+ jobboard._client.delete_prefix.assert_not_called()
357
+ mock__remove_job_from_cache.assert_not_called()
358
+
359
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
360
+ "get_owner_and_data")
361
+ @mock.patch("taskflow.jobs.backends.impl_etcd.EtcdJobBoard."
362
+ "_remove_job_from_cache")
363
+ def test_trash_deleted_job(self, mock__remove_job_from_cache,
364
+ mock_get_owner_and_data):
365
+ mock_get_owner_and_data.return_value = ["owner1", None]
366
+
367
+ _, jobboard = self.create_board()
368
+ jobboard._client = mock.Mock()
369
+
370
+ job = impl_etcd.EtcdJob(jobboard,
371
+ "job7",
372
+ jobboard._client,
373
+ f"/taskflow/jobs/{self.path}/job7")
374
+ self.assertRaisesRegex(exc.NotFound, "Cannot find job",
375
+ jobboard.trash, job, "owner1")
376
+
377
+ jobboard._client.create.assert_not_called()
378
+ jobboard._client.delete_prefix.assert_not_called()
379
+ mock__remove_job_from_cache.assert_not_called()
380
+
381
+
382
+ @testtools.skipIf(not ETCD_AVAILABLE, 'Etcd is not available')
383
+ class EtcdJobBoardTest(test.TestCase, base.BoardTestMixin, EtcdJobBoardMixin):
384
+ def setUp(self):
385
+ super().setUp()
386
+ self.client, self.board = self.create_board()
387
+
388
+ def test__incr(self):
389
+ key = uuidutils.generate_uuid()
390
+
391
+ self.board.connect()
392
+ self.addCleanup(self.board.close)
393
+ self.addCleanup(self.board._client.delete, key)
394
+
395
+ self.assertEqual(1, self.board.incr(key))
396
+ self.assertEqual(2, self.board.incr(key))
397
+ self.assertEqual(3, self.board.incr(key))
398
+
399
+ self.assertEqual(b'3', self.board.get_one(key))
400
+ self.board.close()
401
+
402
+ def test_get_one(self):
403
+ key1 = uuidutils.generate_uuid()
404
+
405
+ self.board.connect()
406
+ self.addCleanup(self.board._client.delete, key1)
407
+
408
+ # put data and get it
409
+ self.board._client.put(key1, "testset1")
410
+ self.assertEqual(b"testset1", self.board.get_one(key1))
411
+
412
+ # delete data and check that it's not found
413
+ self.board._client.delete(key1)
414
+ self.assertIsNone(self.board.get_one(key1))
415
+
416
+ # get a non-existant data
417
+ key2 = uuidutils.generate_uuid()
418
+ # (ensure it doesn't exist)
419
+ self.board._client.delete(key2)
420
+ self.assertIsNone(self.board.get_one(key2))
421
+ self.board.close()
@@ -23,6 +23,11 @@ from taskflow import test
23
23
  from taskflow.tests import utils
24
24
  from taskflow.utils import eventlet_utils as eu
25
25
 
26
+ try:
27
+ from taskflow.engines.action_engine import process_executor as pe
28
+ except ImportError:
29
+ pe = None
30
+
26
31
 
27
32
  class ArgumentsPassingTest(utils.EngineTestBase):
28
33
 
@@ -221,6 +226,7 @@ class ParallelEngineWithEventletTest(ArgumentsPassingTest, test.TestCase):
221
226
  executor=executor)
222
227
 
223
228
 
229
+ @testtools.skipIf(pe is None, 'process_executor is not available')
224
230
  class ParallelEngineWithProcessTest(ArgumentsPassingTest, test.TestCase):
225
231
  _EXECUTOR_WORKERS = 2
226
232
 
@@ -41,6 +41,11 @@ from taskflow.utils import eventlet_utils as eu
41
41
  from taskflow.utils import persistence_utils as p_utils
42
42
  from taskflow.utils import threading_utils as tu
43
43
 
44
+ try:
45
+ from taskflow.engines.action_engine import process_executor as pe
46
+ except ImportError:
47
+ pe = None
48
+
44
49
 
45
50
  # Expected engine transitions when empty workflows are ran...
46
51
  _EMPTY_TRANSITIONS = [
@@ -1494,6 +1499,7 @@ class ParallelEngineWithEventletTest(EngineTaskTest,
1494
1499
  store=store, **kwargs)
1495
1500
 
1496
1501
 
1502
+ @testtools.skipIf(pe is None, 'process_executor is not available')
1497
1503
  class ParallelEngineWithProcessTest(EngineTaskTest,
1498
1504
  EngineMultipleResultsTest,
1499
1505
  EngineLinearFlowTest,
@@ -28,6 +28,11 @@ from taskflow.tests import utils
28
28
  from taskflow.types import failure
29
29
  from taskflow.utils import eventlet_utils as eu
30
30
 
31
+ try:
32
+ from taskflow.engines.action_engine import process_executor as pe
33
+ except ImportError:
34
+ pe = None
35
+
31
36
 
32
37
  class FailingRetry(retry.Retry):
33
38
 
@@ -1313,6 +1318,7 @@ class ParallelEngineWithEventletTest(RetryTest, test.TestCase):
1313
1318
  defer_reverts=defer_reverts)
1314
1319
 
1315
1320
 
1321
+ @testtools.skipIf(pe is None, 'process_executor is not available')
1316
1322
  class ParallelEngineWithProcessTest(RetryTest, test.TestCase):
1317
1323
  _EXECUTOR_WORKERS = 2
1318
1324
 
@@ -25,6 +25,11 @@ from taskflow import test
25
25
  from taskflow.tests import utils
26
26
  from taskflow.utils import eventlet_utils as eu
27
27
 
28
+ try:
29
+ from taskflow.engines.action_engine import process_executor as pe
30
+ except ImportError:
31
+ pe = None
32
+
28
33
 
29
34
  class SuspendingListener(utils.CaptureListener):
30
35
 
@@ -224,6 +229,7 @@ class ParallelEngineWithEventletTest(SuspendTest, test.TestCase):
224
229
  executor=executor)
225
230
 
226
231
 
232
+ @testtools.skipIf(pe is None, 'process_executor is not available')
227
233
  class ParallelEngineWithProcessTest(SuspendTest, test.TestCase):
228
234
  _EXECUTOR_WORKERS = 2
229
235