· 8 years ago · Feb 28, 2018, 11:28 PM
1package com.avenuecode.tiagoprado.mtgmarket;
2
3import static org.assertj.core.api.Assertions.assertThat;
4import java.util.List;
5import java.util.concurrent.Callable;
6import java.util.concurrent.ExecutorService;
7import java.util.concurrent.Executors;
8import java.util.stream.Collectors;
9import java.util.stream.IntStream;
10import org.junit.Test;
11import org.junit.runner.RunWith;
12import org.springframework.beans.factory.annotation.Autowired;
13import org.springframework.boot.test.context.SpringBootTest;
14import org.springframework.boot.test.context.TestConfiguration;
15import org.springframework.context.annotation.Bean;
16import org.springframework.test.context.junit4.SpringRunner;
17import com.avenuecode.tiagoprado.mtgmarket.exceptions.CardDoesNotBelongToPlayerException;
18import com.avenuecode.tiagoprado.mtgmarket.model.domain.Account;
19import com.avenuecode.tiagoprado.mtgmarket.model.domain.CardTransaction;
20import com.avenuecode.tiagoprado.mtgmarket.model.domain.CollectibleCard;
21import com.avenuecode.tiagoprado.mtgmarket.service.CardTransactionService;
22
23@RunWith(SpringRunner.class)
24// @DataJpaTest
25@SpringBootTest
26public class CardTransactionServiceTest {
27
28 @TestConfiguration
29 public static class TestConfigurationOverride {
30
31 @Bean
32 public CardTransactionService service() {
33 return new CardTransactionService();
34 }
35 }
36
37 @Autowired
38 private CardTransactionService service;
39
40
41 @Test
42 public void testParallelTrades() throws Exception {
43
44 Account thirdParty = service.addAccount(new Account(1000L, "third@gmail.com"));
45 CollectibleCard sampleCard = service.addCard(new CollectibleCard("a card", thirdParty));
46
47 ExecutorService executor = Executors.newFixedThreadPool(10);
48
49 List<Account> toAccounts = setupManyAccountsTradeTest(100);
50
51 List<TransactionTransferTest> tests = toAccounts.stream()
52 .map(account -> new TransactionTransferTest(thirdParty, account, sampleCard, 10L))
53 .collect(Collectors.toList());
54
55 List<TransferTestResult> results = executor.invokeAll(tests).stream().map(result -> {
56 try {
57 return result.get();
58 } catch (Exception e) {
59 return new TransferTestResult(e);
60 }
61 }).collect(Collectors.toList());
62
63 executor.shutdown();
64
65 assertThat(results.stream().filter(r -> !r.isSuccessful())
66 .map(r -> r.getError() instanceof CardDoesNotBelongToPlayerException)
67 .collect(Collectors.toList()).size()).isEqualTo(results.size() - 1);
68
69 assertThat(results.stream().filter(TransferTestResult::isSuccessful)
70 .collect(Collectors.toList()).size()).isEqualTo(1);
71 }
72
73 private List<Account> setupManyAccountsTradeTest(int number) {
74 return IntStream.range(0, number)
75 .mapToObj(i -> service.addAccount(new Account(1000L, "someAccount" + i + "@gmail.com")))
76 .collect(Collectors.toList());
77 }
78
79 private class TransferTestResult {
80
81 private CardTransaction transfer;
82
83 private Exception error;
84
85 TransferTestResult(CardTransaction transfer) {
86 this.transfer = transfer;
87 }
88
89 TransferTestResult(Exception e) {
90 error = e;
91 }
92
93 boolean isSuccessful() {
94 return transfer != null;
95 }
96
97 Exception getError() {
98 return error;
99 }
100
101 public CardTransaction getTransfer() {
102 return transfer;
103 }
104 }
105
106 private class TransactionTransferTest implements Callable<TransferTestResult> {
107
108 private Long from;
109 private Long to;
110 private Long card;
111 private Long price;
112
113 TransactionTransferTest(Account from, Account to, CollectibleCard card, Long price) {
114 this(from.getId(), to.getId(), card.getId(), price);
115 }
116
117 TransactionTransferTest(Long from, Long to, Long card, Long price) {
118 this.from = from;
119 this.to = to;
120 this.card = card;
121 this.price = price;
122 }
123
124 @Override
125 public TransferTestResult call() {
126 try {
127 CardTransaction trade = service.tradeCard(card, from, to, price);
128 return new TransferTestResult(trade);
129 } catch (Exception e) {
130 return new TransferTestResult(e);
131 }
132 }
133 }
134}