Skip to content

Commit 1e07c73

Browse files
authored
Add tests on TaskFinalizeService to fix quality threshold regression (#156)
1 parent fac2605 commit 1e07c73

File tree

8 files changed

+222
-77
lines changed

8 files changed

+222
-77
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88

99
- Use poco-chain with poco v5.5.0 and voucher v1.0.0 in tests. (#152)
1010
- Rename `tool` package to `chain` package. (#155)
11+
- Add tests on `TaskFinalizeService` to fix quality threshold regression. (#156)
1112

1213
### Dependency Upgrades
1314

src/main/java/com/iexec/blockchain/command/generic/CommandEngine.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,22 @@ protected CommandEngine(
5050
* @return blockchain object ID if successful
5151
*/
5252
public String startBlockchainCommand(A args, boolean isPriority) {
53-
String chainObjectId = args.getChainObjectId();
53+
final String chainObjectId = args.getChainObjectId();
54+
final String messageDetails = String.format("[chainObjectId:%s, commandArgs:%s]", chainObjectId, args);
5455
if (!blockchainService.canSendBlockchainCommand(args)) {
55-
log.error("Starting blockchain command failed (failing on-chain" +
56-
" checks) [chainObjectId:{}, commandArgs:{}]",
57-
chainObjectId, args);
56+
log.error("Starting blockchain command failed (failing on-chain checks) {}", messageDetails);
5857
return "";
5958
}
6059

6160
if (!updaterService.updateToReceived(args)) {
62-
log.error("Starting blockchain command failed (failing update " +
63-
"to received) [chainObjectId:{}, commandArgs:{}]",
64-
chainObjectId, args);
61+
log.error("Starting blockchain command failed (failing update to received) {}", messageDetails);
6562
return "";
6663
}
67-
log.info("Received command [chainObjectId:{}, commandArgs:{}]",
68-
chainObjectId, args);
64+
log.info("Received command {}", messageDetails);
6965

70-
Runnable runnable = () -> triggerBlockchainCommand(args);
66+
final Runnable runnable = () -> triggerBlockchainCommand(args);
7167
queueService.addExecutionToQueue(runnable, isPriority);
7268

73-
7469
return chainObjectId;
7570
}
7671

src/main/java/com/iexec/blockchain/command/task/TaskControllerV1.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public ResponseEntity<CommandStatus> getStatusForInitializeTaskRequest(@PathVari
8282
@PostMapping("/finalize/{chainTaskId}")
8383
public ResponseEntity<String> requestFinalizeTask(@PathVariable String chainTaskId,
8484
@RequestBody TaskFinalizeArgs args) {
85-
if (!taskFinalizeService.start(chainTaskId, args).isEmpty()) {
85+
if (!taskFinalizeService.start(chainTaskId, args.getResultLink(), args.getCallbackData()).isEmpty()) {
8686
return ResponseEntity.ok(chainTaskId);
8787
}
8888
return ResponseEntity.badRequest().build();

src/main/java/com/iexec/blockchain/command/task/finalize/TaskFinalizeService.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,20 @@
2828
public class TaskFinalizeService extends CommandEngine<TaskFinalize, TaskFinalizeArgs> {
2929

3030
public TaskFinalizeService(
31-
TaskFinalizeBlockchainService blockchainService,
32-
TaskFinalizeStorageService storageService,
33-
QueueService queueService) {
31+
final TaskFinalizeBlockchainService blockchainService,
32+
final TaskFinalizeStorageService storageService,
33+
final QueueService queueService) {
3434
super(blockchainService, storageService, queueService);
3535
}
3636

37-
public String start(String chainTaskId,
38-
com.iexec.common.chain.adapter.args.TaskFinalizeArgs args) {
39-
if (!isByte32(chainTaskId)
40-
|| args == null) {
41-
log.error("At least one bad args [chainTaskId:{}, args:{}]", chainTaskId, args);
37+
public String start(final String chainTaskId, final String resultLink, final String callbackData) {
38+
if (!isByte32(chainTaskId) || resultLink == null || callbackData == null) {
39+
log.error("At least one bad args [chainTaskId:{}, resultLink:{}, callbackData:{}]",
40+
chainTaskId, resultLink, callbackData);
4241
return "";
4342
}
4443
return startBlockchainCommand(
45-
new TaskFinalizeArgs(chainTaskId, args.getResultLink(), args.getCallbackData()),
44+
new TaskFinalizeArgs(chainTaskId, resultLink, callbackData),
4645
true);
4746
}
4847

src/main/java/com/iexec/blockchain/command/task/initialize/TaskInitializeService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@
2727
public class TaskInitializeService extends CommandEngine<TaskInitialize, TaskInitializeArgs> {
2828

2929
public TaskInitializeService(
30-
TaskInitializeBlockchainService blockchainService,
31-
TaskInitializeStorageService updaterService,
32-
QueueService queueService) {
30+
final TaskInitializeBlockchainService blockchainService,
31+
final TaskInitializeStorageService updaterService,
32+
final QueueService queueService) {
3333
super(blockchainService, updaterService, queueService);
3434
}
3535

36-
public String start(String chainDealId, int taskIndex) {
36+
public String start(final String chainDealId, final int taskIndex) {
3737
if (!isByte32(chainDealId) || taskIndex < 0) {
3838
return "";
3939
}
40-
String chainTaskId = ChainUtils.generateChainTaskId(chainDealId, taskIndex);
40+
final String chainTaskId = ChainUtils.generateChainTaskId(chainDealId, taskIndex);
4141
return startBlockchainCommand(
4242
new TaskInitializeArgs(chainTaskId, chainDealId, taskIndex),
4343
false);

src/test/java/com/iexec/blockchain/command/task/TaskControllerV1Tests.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024-2024 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2024 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,20 +20,21 @@
2020
import com.iexec.blockchain.command.task.finalize.TaskFinalizeService;
2121
import com.iexec.blockchain.command.task.initialize.TaskInitializeService;
2222
import com.iexec.common.chain.adapter.args.TaskFinalizeArgs;
23-
import org.junit.jupiter.api.BeforeEach;
2423
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
2525
import org.junit.jupiter.params.ParameterizedTest;
2626
import org.junit.jupiter.params.provider.EnumSource;
2727
import org.mockito.InjectMocks;
2828
import org.mockito.Mock;
29-
import org.mockito.MockitoAnnotations;
29+
import org.mockito.junit.jupiter.MockitoExtension;
3030
import org.springframework.http.ResponseEntity;
3131

3232
import java.util.Optional;
3333

3434
import static org.assertj.core.api.Assertions.assertThat;
3535
import static org.mockito.Mockito.when;
3636

37+
@ExtendWith(MockitoExtension.class)
3738
class TaskControllerV1Tests {
3839

3940
private static final String CHAIN_DEAL_ID = "0x1";
@@ -47,11 +48,6 @@ class TaskControllerV1Tests {
4748
@InjectMocks
4849
private TaskControllerV1 taskController;
4950

50-
@BeforeEach
51-
void init() {
52-
MockitoAnnotations.openMocks(this);
53-
}
54-
5551
// region requestInitializeTask
5652
@Test
5753
void shouldNotifyInitializeCommandSubmissionFailure() {
@@ -88,14 +84,14 @@ void shouldNotReturnInitializeCommandStatusWhenEmpty() {
8884
// region requestFinalizeTask
8985
@Test
9086
void shouldNotifyFinalizeCommandSubmissionFailure() {
91-
when(taskFinalizeService.start(CHAIN_TASK_ID, TaskFinalizeArgs.builder().build())).thenReturn("");
87+
when(taskFinalizeService.start(CHAIN_TASK_ID, null, null)).thenReturn("");
9288
assertThat(taskController.requestFinalizeTask(CHAIN_TASK_ID, TaskFinalizeArgs.builder().build()))
9389
.isEqualTo(ResponseEntity.badRequest().build());
9490
}
9591

9692
@Test
9793
void shouldNotifyFinalizeCommandSubmissionSuccess() {
98-
when(taskFinalizeService.start(CHAIN_TASK_ID, TaskFinalizeArgs.builder().build())).thenReturn(CHAIN_TASK_ID);
94+
when(taskFinalizeService.start(CHAIN_TASK_ID, null, null)).thenReturn(CHAIN_TASK_ID);
9995
assertThat(taskController.requestFinalizeTask(CHAIN_TASK_ID, TaskFinalizeArgs.builder().build()))
10096
.isEqualTo(ResponseEntity.ok(CHAIN_TASK_ID));
10197
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Copyright 2024 IEXEC BLOCKCHAIN TECH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.iexec.blockchain.command.task.finalize;
18+
19+
import com.iexec.blockchain.api.CommandStatus;
20+
import com.iexec.blockchain.chain.QueueService;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.ExtendWith;
23+
import org.junit.jupiter.params.ParameterizedTest;
24+
import org.junit.jupiter.params.provider.Arguments;
25+
import org.junit.jupiter.params.provider.MethodSource;
26+
import org.mockito.InjectMocks;
27+
import org.mockito.Mock;
28+
import org.mockito.junit.jupiter.MockitoExtension;
29+
import org.web3j.protocol.core.methods.response.TransactionReceipt;
30+
31+
import java.util.Optional;
32+
import java.util.stream.Stream;
33+
34+
import static com.iexec.commons.poco.utils.BytesUtils.EMPTY_ADDRESS;
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
import static org.mockito.ArgumentMatchers.any;
37+
import static org.mockito.ArgumentMatchers.eq;
38+
import static org.mockito.Mockito.*;
39+
40+
@ExtendWith(MockitoExtension.class)
41+
class TaskFinalizeServiceTests {
42+
43+
private static final String CHAIN_TASK_ID =
44+
"0xe90fc4654b5ea32ad8689091e7610cad7ee5c8b9b1a6e39401b57d90343bfcaa";
45+
private static final String RESULT_LINK = "/ipfs/QmeQHGKFAkEkA5tm3kuXqBM9zz9JorkvCsAJ2bzAAh6NX4";
46+
47+
@InjectMocks
48+
private TaskFinalizeService taskFinalizeService;
49+
@Mock
50+
private TaskFinalizeBlockchainService blockchainService;
51+
@Mock
52+
private TaskFinalizeStorageService updaterService;
53+
@Mock
54+
private QueueService queueService;
55+
56+
private final TaskFinalizeArgs args = new TaskFinalizeArgs(CHAIN_TASK_ID, RESULT_LINK, EMPTY_ADDRESS);
57+
58+
// region start
59+
@Test
60+
void shouldFinalizeTask() {
61+
when(blockchainService.canSendBlockchainCommand(args)).thenReturn(true);
62+
when(updaterService.updateToReceived(args)).thenReturn(true);
63+
final String chainTaskId = taskFinalizeService.start(CHAIN_TASK_ID, RESULT_LINK, EMPTY_ADDRESS);
64+
assertThat(chainTaskId).isEqualTo(CHAIN_TASK_ID);
65+
verify(queueService).addExecutionToQueue(any(Runnable.class), eq(true));
66+
}
67+
68+
@ParameterizedTest
69+
@MethodSource("provideTaskFinalizeBadParameters")
70+
void shouldNotFinalizeTaskWithBadParameters(final String chainTaskId, final String resultLink, final String callbackData) {
71+
assertThat(taskFinalizeService.start(chainTaskId, resultLink, callbackData)).isEmpty();
72+
}
73+
74+
private static Stream<Arguments> provideTaskFinalizeBadParameters() {
75+
return Stream.of(
76+
Arguments.of("not-a-task", RESULT_LINK, EMPTY_ADDRESS),
77+
Arguments.of(CHAIN_TASK_ID, null, EMPTY_ADDRESS),
78+
Arguments.of(CHAIN_TASK_ID, RESULT_LINK, null)
79+
);
80+
}
81+
82+
@Test
83+
void shouldNotFinalizeTaskSinceCannotOnChain() {
84+
when(blockchainService.canSendBlockchainCommand(args)).thenReturn(false);
85+
86+
final String chainTaskId = taskFinalizeService.start(CHAIN_TASK_ID, RESULT_LINK, EMPTY_ADDRESS);
87+
88+
assertThat(chainTaskId).isEmpty();
89+
verifyNoInteractions(queueService);
90+
}
91+
92+
@Test
93+
void shouldNotFinalizeTaskSinceCannotUpdate() {
94+
when(blockchainService.canSendBlockchainCommand(args)).thenReturn(true);
95+
when(updaterService.updateToReceived(args)).thenReturn(false);
96+
97+
final String chainTaskId = taskFinalizeService.start(CHAIN_TASK_ID, RESULT_LINK, EMPTY_ADDRESS);
98+
99+
assertThat(chainTaskId).isEmpty();
100+
verifyNoInteractions(queueService);
101+
}
102+
// endregion
103+
104+
// region triggerBlockchainCommand
105+
@Test
106+
void triggerFinalizeTask() throws Exception {
107+
final TransactionReceipt receipt = mock(TransactionReceipt.class);
108+
when(updaterService.updateToProcessing(CHAIN_TASK_ID)).thenReturn(true);
109+
when(blockchainService.sendBlockchainCommand(args)).thenReturn(receipt);
110+
111+
taskFinalizeService.triggerBlockchainCommand(args);
112+
verify(updaterService).updateToFinal(CHAIN_TASK_ID, receipt);
113+
}
114+
115+
@Test
116+
void shouldNotTriggerFinalizeTaskSinceCannotUpdate() {
117+
final TransactionReceipt receipt = mock(TransactionReceipt.class);
118+
when(updaterService.updateToProcessing(CHAIN_TASK_ID)).thenReturn(false);
119+
120+
taskFinalizeService.triggerBlockchainCommand(args);
121+
verify(updaterService, never()).updateToFinal(CHAIN_TASK_ID, receipt);
122+
verifyNoInteractions(blockchainService);
123+
}
124+
125+
@Test
126+
void shouldNotTriggerFinalizeTaskSinceReceiptIsNull() throws Exception {
127+
when(updaterService.updateToProcessing(CHAIN_TASK_ID)).thenReturn(true);
128+
when(blockchainService.sendBlockchainCommand(args)).thenReturn(null);
129+
130+
taskFinalizeService.triggerBlockchainCommand(args);
131+
verify(updaterService).updateToFinal(CHAIN_TASK_ID, null);
132+
}
133+
// endregion
134+
135+
// region getStatusForCommand
136+
@Test
137+
void shouldGetStatusForFinalizeTaskRequest() {
138+
when(updaterService.getStatusForCommand(CHAIN_TASK_ID)).thenReturn(Optional.of(CommandStatus.PROCESSING));
139+
assertThat(taskFinalizeService.getStatusForCommand(CHAIN_TASK_ID)).contains(CommandStatus.PROCESSING);
140+
}
141+
142+
@Test
143+
void shouldNotGetStatusForFinalizeTaskRequestSinceNoRequest() {
144+
when(updaterService.getStatusForCommand(CHAIN_TASK_ID)).thenReturn(Optional.empty());
145+
assertThat(taskFinalizeService.getStatusForCommand(CHAIN_TASK_ID)).isEmpty();
146+
}
147+
// endregion
148+
149+
}

0 commit comments

Comments
 (0)