2121import org .apache .commons .lang3 .RandomStringUtils ;
2222import org .apache .commons .lang3 .StringUtils ;
2323import org .junit .jupiter .api .Assertions ;
24+ import org .junit .jupiter .api .BeforeEach ;
2425import org .junit .jupiter .api .Test ;
2526import org .springframework .beans .factory .annotation .Autowired ;
2627import org .springframework .boot .test .context .SpringBootTest ;
3132import org .web3j .crypto .Sign ;
3233
3334import java .math .BigInteger ;
35+ import java .util .ArrayList ;
36+ import java .util .List ;
3437import java .util .Optional ;
38+ import java .util .concurrent .CompletableFuture ;
39+ import java .util .stream .IntStream ;
3540
3641import static com .iexec .common .chain .ChainTaskStatus .ACTIVE ;
3742import static com .iexec .common .chain .ChainTaskStatus .UNSET ;
@@ -42,6 +47,7 @@ class IntegrationTests {
4247
4348 public static final String USER = "admin" ;
4449 public static final String PASSWORD = "whatever" ;
50+ public static final int BLOCK_TIME_MS = 1000 ;
4551
4652 @ LocalServerPort
4753 private int randomServerPort ;
@@ -63,9 +69,83 @@ class IntegrationTests {
6369
6470 @ Autowired
6571 private SignerService signerService ;
66-
72+ private BlockchainAdapterApiClient appClient ;
73+
74+ @ BeforeEach
75+ void setUp () {
76+ appClient = FeignUtils .getFeignBuilder (USER , PASSWORD )
77+ .target (BlockchainAdapterApiClient .class , getBaseUrl ());
78+ }
79+
6780 @ Test
6881 public void shouldBeFinalized () throws Exception {
82+ String dealId = triggerDeal (1 );
83+
84+ String chainTaskId = appClient .requestInitializeTask (dealId , 0 );
85+ Assertions .assertTrue (StringUtils .isNotEmpty (chainTaskId ));
86+ System .out .println ("Requested task initialize: " + chainTaskId );
87+ //should wait since returned taskID is computed, initialize is not mined yet
88+ waitStatus (chainTaskId , ACTIVE , 1000 , 10 );
89+
90+ String someBytes32Payload = TeeUtils .TEE_TAG ;
91+ String enclaveChallenge = BytesUtils .EMPTY_ADDRESS ;
92+ String enclaveSignature = BytesUtils .bytesToString (new byte [65 ]);
93+ WorkerpoolAuthorization workerpoolAuthorization =
94+ mockAuthorization (chainTaskId , enclaveChallenge );
95+ TaskContributeArgs contributeArgs = new TaskContributeArgs (
96+ someBytes32Payload ,
97+ workerpoolAuthorization .getSignature ().getValue (),
98+ enclaveChallenge ,
99+ enclaveSignature );
100+ String contributeResponseBody = appClient .requestContributeTask (chainTaskId , contributeArgs );
101+ Assertions .assertTrue (StringUtils .isNotEmpty (contributeResponseBody ));
102+ System .out .println ("Requested task contribute: " + contributeResponseBody );
103+ waitStatus (chainTaskId , ChainTaskStatus .REVEALING , 1000 , 10 );
104+
105+ TaskRevealArgs taskRevealArgs = new TaskRevealArgs (someBytes32Payload );
106+ String revealResponseBody = appClient .requestRevealTask (chainTaskId , taskRevealArgs );
107+ Assertions .assertTrue (StringUtils .isNotEmpty (revealResponseBody ));
108+ System .out .println ("Requested task reveal: " + revealResponseBody );
109+
110+ waitBeforeFinalizing (chainTaskId );
111+ TaskFinalizeArgs taskFinalizeArgs = new TaskFinalizeArgs ();
112+ String finalizeResponseBody = appClient .requestFinalizeTask (chainTaskId , taskFinalizeArgs );
113+ Assertions .assertTrue (StringUtils .isNotEmpty (finalizeResponseBody ));
114+ System .out .println ("Requested task finalize: " + finalizeResponseBody );
115+ waitStatus (chainTaskId , ChainTaskStatus .COMPLETED , 1000 , 10 );
116+ }
117+
118+ @ Test
119+ public void shouldBurstTransactionsWithAverageOfOneTxPerBlock (){
120+ int taskVolume = 10 ;//small volume ensures reasonable execution time on CI/CD
121+ String dealId = triggerDeal (taskVolume );
122+ List <CompletableFuture <Void >> txCompletionWatchers = new ArrayList <>();
123+
124+ IntStream .range (0 , taskVolume )
125+ .forEach (taskIndex -> {
126+ //burst transactions (fast sequence) (send "initialize" tx examples for simplicity)
127+ String chainTaskId = appClient .requestInitializeTask (dealId , taskIndex );
128+ Assertions .assertTrue (StringUtils .isNotEmpty (chainTaskId ));
129+ System .out .printf ("Requested task initialize " +
130+ "[index:%s, chainTaskId:%s]\n " , taskIndex , chainTaskId );
131+ //wait tx completion outside
132+ txCompletionWatchers .add (CompletableFuture .runAsync (() -> {
133+ try {
134+ //maximum waiting time equals nb of submitted txs
135+ //1 tx/block means N txs / N blocks
136+ waitStatus (chainTaskId , ACTIVE , BLOCK_TIME_MS , taskVolume );
137+ //no need to wait for propagation update in db
138+ Assertions .assertTrue (true );
139+ } catch (Exception e ) {
140+ e .printStackTrace ();
141+ Assertions .fail ();
142+ }
143+ }));
144+ });
145+ txCompletionWatchers .forEach (CompletableFuture ::join );
146+ }
147+
148+ private String triggerDeal (int taskVolume ) {
69149 String appAddress = iexecHubService .createApp (buildRandomName ("app" ),
70150 "docker.io/repo/name:1.0.0" ,
71151 "DOCKER" ,
@@ -82,9 +162,9 @@ public void shouldBeFinalized() throws Exception {
82162 30 , 1 );
83163 System .out .println ("Created datasetAddress: " + datasetAddress );
84164
85- AppOrder signedAppOrder = signerService .signAppOrder (buildAppOrder (appAddress ));
86- WorkerpoolOrder signedWorkerpoolOrder = signerService .signWorkerpoolOrder (buildWorkerpoolOrder (workerpool ));
87- DatasetOrder signedDatasetOrder = signerService .signDatasetOrder (buildDatasetOrder (datasetAddress ));
165+ AppOrder signedAppOrder = signerService .signAppOrder (buildAppOrder (appAddress , taskVolume ));
166+ WorkerpoolOrder signedWorkerpoolOrder = signerService .signWorkerpoolOrder (buildWorkerpoolOrder (workerpool , taskVolume ));
167+ DatasetOrder signedDatasetOrder = signerService .signDatasetOrder (buildDatasetOrder (datasetAddress , taskVolume ));
88168 RequestOrder signedRequestOrder = signerService .signRequestOrder (buildRequestOrder (signedAppOrder ,
89169 signedWorkerpoolOrder ,
90170 signedDatasetOrder ,
@@ -108,53 +188,19 @@ public void shouldBeFinalized() throws Exception {
108188 //existence for double checking
109189 Optional <ChainDeal > chainDeal = iexecHubService .getChainDeal (dealId );
110190 Assertions .assertTrue (chainDeal .isPresent ());
111-
112- BlockchainAdapterApiClient appClient = FeignUtils .getFeignBuilder (USER , PASSWORD )
113- .target (BlockchainAdapterApiClient .class , getBaseUrl ());
114-
115- String chainTaskId = appClient .requestInitializeTask (dealId , 0 );
116- Assertions .assertTrue (StringUtils .isNotEmpty (chainTaskId ));
117- System .out .println ("Requested task initialize: " + chainTaskId );
118- //should wait since returned taskID is computed, initialize is not mined yet
119- waitStatus (chainTaskId , ACTIVE );
120-
121- String someBytes32Payload = TeeUtils .TEE_TAG ;
122- String enclaveChallenge = BytesUtils .EMPTY_ADDRESS ;
123- String enclaveSignature = BytesUtils .bytesToString (new byte [65 ]);
124- WorkerpoolAuthorization workerpoolAuthorization =
125- mockAuthorization (chainTaskId , enclaveChallenge );
126- TaskContributeArgs contributeArgs = new TaskContributeArgs (
127- someBytes32Payload ,
128- workerpoolAuthorization .getSignature ().getValue (),
129- enclaveChallenge ,
130- enclaveSignature );
131- String contributeResponseBody = appClient .requestContributeTask (chainTaskId , contributeArgs );
132- Assertions .assertTrue (StringUtils .isNotEmpty (contributeResponseBody ));
133- System .out .println ("Requested task contribute: " + contributeResponseBody );
134- waitStatus (chainTaskId , ChainTaskStatus .REVEALING );
135-
136- TaskRevealArgs taskRevealArgs = new TaskRevealArgs (someBytes32Payload );
137- String revealResponseBody = appClient .requestRevealTask (chainTaskId , taskRevealArgs );
138- Assertions .assertTrue (StringUtils .isNotEmpty (revealResponseBody ));
139- System .out .println ("Requested task reveal: " + revealResponseBody );
140-
141- waitBeforeFinalizing (chainTaskId );
142- TaskFinalizeArgs taskFinalizeArgs = new TaskFinalizeArgs ();
143- String finalizeResponseBody = appClient .requestFinalizeTask (chainTaskId , taskFinalizeArgs );
144- Assertions .assertTrue (StringUtils .isNotEmpty (finalizeResponseBody ));
145- System .out .println ("Requested task finalize: " + finalizeResponseBody );
146- waitStatus (chainTaskId , ChainTaskStatus .COMPLETED );
191+ return dealId ;
147192 }
148193
194+
149195 private String buildRandomName (String baseName ) {
150196 return baseName + "-" + RandomStringUtils .randomAlphabetic (10 );
151197 }
152198
153- private AppOrder buildAppOrder (String appAddress ) {
199+ private AppOrder buildAppOrder (String appAddress , int volume ) {
154200 return AppOrder .builder ()
155201 .app (appAddress )
156202 .price (BigInteger .ZERO )
157- .volume (BigInteger .ONE )
203+ .volume (BigInteger .valueOf ( volume ) )
158204 .tag (BytesUtils .EMPTY_HEXASTRING_64 )
159205 .datasetrestrict (BytesUtils .EMPTY_ADDRESS )
160206 .workerpoolrestrict (BytesUtils .EMPTY_ADDRESS )
@@ -163,11 +209,11 @@ private AppOrder buildAppOrder(String appAddress) {
163209 .build ();
164210 }
165211
166- private WorkerpoolOrder buildWorkerpoolOrder (String workerpoolAddress ) {
212+ private WorkerpoolOrder buildWorkerpoolOrder (String workerpoolAddress , int volume ) {
167213 return WorkerpoolOrder .builder ()
168214 .workerpool (workerpoolAddress )
169215 .price (BigInteger .ZERO )
170- .volume (BigInteger .ONE )
216+ .volume (BigInteger .valueOf ( volume ) )
171217 .tag (BytesUtils .EMPTY_HEXASTRING_64 )
172218 .trust (BigInteger .ZERO )
173219 .category (BigInteger .ZERO )
@@ -178,11 +224,11 @@ private WorkerpoolOrder buildWorkerpoolOrder(String workerpoolAddress) {
178224 .build ();
179225 }
180226
181- private DatasetOrder buildDatasetOrder (String datasetAddress ) {
227+ private DatasetOrder buildDatasetOrder (String datasetAddress , int volume ) {
182228 return DatasetOrder .builder ()
183229 .dataset (datasetAddress )
184230 .price (BigInteger .ZERO )
185- .volume (BigInteger .ONE )
231+ .volume (BigInteger .valueOf ( volume ) )
186232 .tag (BytesUtils .EMPTY_HEXASTRING_64 )
187233 .apprestrict (BytesUtils .EMPTY_ADDRESS )
188234 .workerpoolrestrict (BytesUtils .EMPTY_ADDRESS )
@@ -197,14 +243,21 @@ private RequestOrder buildRequestOrder(
197243 DatasetOrder datasetOrder ,
198244 String requesterAddress ,
199245 DealParams dealParams ) {
246+ boolean isCompatibleVolume =
247+ appOrder .getVolume ().equals (workerpoolOrder .getVolume ())
248+ && appOrder .getVolume ().equals (datasetOrder .getVolume ());
249+ if (!isCompatibleVolume ){
250+ System .out .println ("Volumes are not compatible" );
251+ return null ;
252+ }
200253 return RequestOrder .builder ()
201254 .app (appOrder .getApp ())
202255 .appmaxprice (appOrder .getAppprice ())
203256 .workerpool (workerpoolOrder .getWorkerpool ())
204257 .workerpoolmaxprice (workerpoolOrder .getWorkerpoolprice ())
205258 .dataset (datasetOrder .getDataset ())
206259 .datasetmaxprice (datasetOrder .getDatasetprice ())
207- .volume (BigInteger . ONE )
260+ .volume (appOrder . getVolume () )
208261 .category (BigInteger .ZERO )
209262 .trust (BigInteger .ZERO )
210263 .tag (BytesUtils .EMPTY_HEXASTRING_64 )
@@ -217,15 +270,18 @@ private RequestOrder buildRequestOrder(
217270 .build ();
218271 }
219272
220- private void waitStatus (String chainTaskId , ChainTaskStatus statusToWait ) throws Exception {
273+ /**
274+ *
275+ * @param pollingTimeMs recommended value is block time
276+ */
277+ private void waitStatus (String chainTaskId , ChainTaskStatus statusToWait , int pollingTimeMs , int maxAttempts ) throws Exception {
221278 ChainTaskStatus status = iexecHubService .getChainTask (chainTaskId )
222279 .map (ChainTask ::getStatus )
223280 .orElse (UNSET );
224- int maxAttempts = 20 ;
225281 int attempts = 0 ;
226282 while (!status .equals (statusToWait )) {
227- System .out .println ("Status is: " + status );
228- Thread .sleep (100 );
283+ System .out .printf ("Status [status:%s, chainTaskId:%s] \n " , status , chainTaskId );
284+ Thread .sleep (pollingTimeMs );
229285 status = iexecHubService .getChainTask (chainTaskId )
230286 .map (ChainTask ::getStatus )
231287 .orElse (UNSET );
@@ -234,7 +290,7 @@ private void waitStatus(String chainTaskId, ChainTaskStatus statusToWait) throws
234290 throw new Exception ("Too long to wait for task: " + chainTaskId );
235291 }
236292 }
237- System .out .println ("Status reached: " + status );
293+ System .out .printf ("Status reached [status:%s, chainTaskId:%s] \n " , status , chainTaskId );
238294 }
239295
240296 private void waitBeforeFinalizing (String chainTaskId ) throws Exception {
0 commit comments