1+ /*
2+ * Copyright 2023-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+
117package com .iexec .core .detector .replicate ;
218
319import com .iexec .common .replicate .ReplicateStatus ;
420import com .iexec .common .replicate .ReplicateStatusDetails ;
521import com .iexec .common .replicate .ReplicateStatusUpdate ;
622import com .iexec .commons .poco .chain .ChainReceipt ;
23+ import com .iexec .commons .poco .task .TaskDescription ;
24+ import com .iexec .commons .poco .utils .BytesUtils ;
725import com .iexec .core .chain .IexecHubService ;
826import com .iexec .core .chain .Web3jService ;
927import com .iexec .core .configuration .CronConfiguration ;
1432import com .iexec .core .task .TaskStatus ;
1533import org .junit .jupiter .api .BeforeEach ;
1634import org .junit .jupiter .api .Test ;
35+ import org .junit .jupiter .params .ParameterizedTest ;
36+ import org .junit .jupiter .params .provider .EnumSource ;
1737import org .mockito .*;
38+ import org .springframework .test .util .ReflectionTestUtils ;
1839
19- import java .util . Arrays ;
40+ import java .math . BigInteger ;
2041import java .util .Collections ;
2142
2243import static com .iexec .common .replicate .ReplicateStatus .*;
2344import static com .iexec .common .replicate .ReplicateStatusModifier .WORKER ;
24- import static org .mockito .ArgumentMatchers .any ;
25- import static org .mockito .ArgumentMatchers . eq ;
45+ import static org .mockito .ArgumentMatchers .* ;
46+ import static org .mockito .Mockito . never ;
2647import static org .mockito .Mockito .when ;
2748
2849class ContributionAndFinalizationUnnotifiedDetectorTests {
@@ -51,9 +72,23 @@ class ContributionAndFinalizationUnnotifiedDetectorTests {
5172 @ BeforeEach
5273 void init () {
5374 MockitoAnnotations .openMocks (this );
75+ ReflectionTestUtils .setField (detector , "detectorRate" , 1000 );
76+ when (iexecHubService .getTaskDescription (anyString ())).thenReturn (TaskDescription .builder ()
77+ .trust (BigInteger .ONE )
78+ .isTeeTask (true )
79+ .callback (BytesUtils .EMPTY_ADDRESS )
80+ .build ());
81+ }
82+
83+ private Replicate getReplicateWithStatus (ReplicateStatus replicateStatus ) {
84+ Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
85+ ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ()
86+ .modifier (WORKER ).status (replicateStatus ).build ();
87+ replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
88+ return replicate ;
5489 }
5590
56- // region Detector aggregator
91+ // region detectOnChainChanges
5792
5893 /**
5994 * When running {@link ContributionAndFinalizationUnnotifiedDetector#detectOnChainChanges} 10 times,
@@ -68,10 +103,7 @@ void shouldDetectBothChangesOnChain() {
68103 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
69104 when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
70105
71- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
72- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (CONTRIBUTE_AND_FINALIZE_ONGOING ).modifier (WORKER ).build ();
73- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
74-
106+ Replicate replicate = getReplicateWithStatus (CONTRIBUTE_AND_FINALIZE_ONGOING );
75107 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
76108 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (true );
77109 when (web3jService .getLatestBlockNumber ()).thenReturn (11L );
@@ -97,17 +129,14 @@ void shouldDetectBothChangesOnChain() {
97129
98130 // endregion
99131
100- //region detectOnchainDoneWhenOffchainOngoing (ContributeAndFinalizeOngoing)
132+ // region detectOnchainDoneWhenOffchainOngoing (ContributeAndFinalizeOngoing)
101133
102134 @ Test
103- void shouldDetectUnNotifiedContributeAndFinalizeDoneAfterContributeAndFinalizeOngoing () {
135+ void shouldDetectMissedUpdateSinceOffChainOngoing () {
104136 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
105- when (taskService .findByCurrentStatus (Arrays .asList (TaskStatus .INITIALIZED , TaskStatus .RUNNING ))).thenReturn (Collections .singletonList (task ));
106-
107- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
108- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (CONTRIBUTE_AND_FINALIZE_ONGOING ).build ();
109- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
137+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
110138
139+ Replicate replicate = getReplicateWithStatus (CONTRIBUTE_AND_FINALIZE_ONGOING );
111140 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
112141 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (true );
113142 when (web3jService .getLatestBlockNumber ()).thenReturn (11L );
@@ -130,53 +159,45 @@ void shouldDetectUnNotifiedContributeAndFinalizeDoneAfterContributeAndFinalizeOn
130159 }
131160
132161 @ Test
133- void shouldDetectUnNotifiedContributeAndFinalizeDoneSinceBeforeContributeAndFinalizeOngoing () {
162+ void shouldNotDetectMissedUpdateSinceNotOffChainOngoing () {
134163 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
135- when (taskService .findByCurrentStatus (Arrays .asList (TaskStatus .INITIALIZED , TaskStatus .RUNNING ))).thenReturn (Collections .singletonList (task ));
136-
137- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
138- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (COMPUTED ).build ();
139- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
164+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
140165
166+ Replicate replicate = getReplicateWithStatus (COMPUTED );
141167 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
142168 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (true );
143169
144170 detector .detectOnchainDoneWhenOffchainOngoing ();
145171
146- Mockito .verify (replicatesService , Mockito . times ( 0 ))
172+ Mockito .verify (replicatesService , never ( ))
147173 .updateReplicateStatus (any (), any (), any (), any (ReplicateStatusDetails .class ));
148174 }
149175
150176 @ Test
151- void shouldNotDetectUnNotifiedContributeAndFinalizeDoneSinceNotFinalizedOnChain () {
177+ void shouldNotDetectMissedUpdateSinceNotOnChainDone () {
152178 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
153- when (taskService .findByCurrentStatus (Arrays .asList (TaskStatus .INITIALIZED , TaskStatus .RUNNING ))).thenReturn (Collections .singletonList (task ));
154-
155- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
156- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (CONTRIBUTE_AND_FINALIZE_ONGOING ).build ();
157- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
179+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
158180
181+ Replicate replicate = getReplicateWithStatus (CONTRIBUTE_AND_FINALIZE_ONGOING );
159182 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
160183 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (false );
161184 detector .detectOnchainDoneWhenOffchainOngoing ();
162185
163- Mockito .verify (replicatesService , Mockito . times ( 0 ))
186+ Mockito .verify (replicatesService , never ( ))
164187 .updateReplicateStatus (any (), any (), any (), any (ReplicateStatusDetails .class ));
165188 }
166189
167190 // endregion
168191
169- //region detectOnchainDone (REVEALED)
192+ // region detectOnchainDone (REVEALED)
170193
171- @ Test
172- void shouldDetectUnNotifiedContributeAndFinalizeOngoing () {
194+ @ ParameterizedTest
195+ @ EnumSource (value = ReplicateStatus .class , names = {"COMPUTED" , "CONTRIBUTE_AND_FINALIZE_ONGOING" })
196+ void shouldDetectMissedUpdateSinceOnChainDoneNotOffChainDone (ReplicateStatus replicateStatus ) {
173197 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
174- when (taskService .findByCurrentStatus (Arrays .asList (TaskStatus .INITIALIZED , TaskStatus .RUNNING ))).thenReturn (Collections .singletonList (task ));
175-
176- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
177- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (CONTRIBUTE_AND_FINALIZE_ONGOING ).build ();
178- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
198+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
179199
200+ Replicate replicate = getReplicateWithStatus (replicateStatus );
180201 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
181202 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (true );
182203 when (web3jService .getLatestBlockNumber ()).thenReturn (11L );
@@ -197,19 +218,38 @@ void shouldDetectUnNotifiedContributeAndFinalizeOngoing() {
197218 }
198219
199220 @ Test
200- void shouldNotDetectUnNotifiedContributedSinceContributeAndFinalizeDone () {
221+ void shouldNotDetectMissedUpdateSinceOnChainDoneAndOffChainDone () {
201222 Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
202- when (taskService .findByCurrentStatus (Arrays .asList (TaskStatus .INITIALIZED , TaskStatus .RUNNING ))).thenReturn (Collections .singletonList (task ));
203-
204- Replicate replicate = new Replicate (WALLET_ADDRESS , CHAIN_TASK_ID );
205- ReplicateStatusUpdate statusUpdate = ReplicateStatusUpdate .builder ().status (CONTRIBUTE_AND_FINALIZE_DONE ).build ();
206- replicate .setStatusUpdateList (Collections .singletonList (statusUpdate ));
223+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
207224
225+ Replicate replicate = getReplicateWithStatus (CONTRIBUTE_AND_FINALIZE_DONE );
208226 when (replicatesService .getReplicates (CHAIN_TASK_ID )).thenReturn (Collections .singletonList (replicate ));
209227 when (iexecHubService .isRevealed (CHAIN_TASK_ID , WALLET_ADDRESS )).thenReturn (true );
210228 detector .detectOnchainDone ();
211229
212- Mockito .verify (replicatesService , Mockito .times (0 ))
230+ Mockito .verify (replicatesService , never ())
231+ .updateReplicateStatus (any (), any (), any (), any (ReplicateStatusDetails .class ));
232+ }
233+
234+ @ Test
235+ void shouldNotDetectMissedUpdateSinceOnChainDoneAndNotEligibleToContributeAndFinalize () {
236+ when (iexecHubService .getTaskDescription (CHAIN_TASK_ID )).thenReturn (
237+ TaskDescription .builder ().trust (BigInteger .ONE ).isTeeTask (true ).callback ("0x2" ).build ());
238+ Task task = Task .builder ().chainTaskId (CHAIN_TASK_ID ).build ();
239+ when (taskService .findByCurrentStatus (TaskStatus .getWaitingContributionStatuses ())).thenReturn (Collections .singletonList (task ));
240+
241+ Replicate replicate = getReplicateWithStatus (CONTRIBUTING );
242+ when (replicatesService .getReplicates (any ())).thenReturn (Collections .singletonList (replicate ));
243+ when (iexecHubService .isContributed (any (), any ())).thenReturn (true );
244+ when (web3jService .getLatestBlockNumber ()).thenReturn (11L );
245+ when (iexecHubService .getContributionBlock (anyString (), anyString (), anyLong ())).thenReturn (ChainReceipt .builder ()
246+ .blockNumber (10L )
247+ .txHash ("0xabcef" )
248+ .build ());
249+
250+ detector .detectOnchainDone ();
251+
252+ Mockito .verify (replicatesService , never ())
213253 .updateReplicateStatus (any (), any (), any (), any (ReplicateStatusDetails .class ));
214254 }
215255
0 commit comments