1 | package clarin.cmdi.componentregistry.rest; |
---|
2 | |
---|
3 | import clarin.cmdi.componentregistry.impl.database.ComponentRegistryTestDatabase; |
---|
4 | import clarin.cmdi.componentregistry.model.BaseDescription; |
---|
5 | import clarin.cmdi.componentregistry.model.ComponentDescription; |
---|
6 | import clarin.cmdi.componentregistry.model.ProfileDescription; |
---|
7 | import clarin.cmdi.componentregistry.model.RegisterResponse; |
---|
8 | |
---|
9 | import com.sun.jersey.api.client.ClientResponse; |
---|
10 | import com.sun.jersey.multipart.FormDataMultiPart; |
---|
11 | |
---|
12 | import java.io.InputStream; |
---|
13 | import java.util.ArrayList; |
---|
14 | import java.util.Arrays; |
---|
15 | import java.util.Collections; |
---|
16 | import java.util.Comparator; |
---|
17 | import java.util.List; |
---|
18 | |
---|
19 | import javax.ws.rs.core.MediaType; |
---|
20 | |
---|
21 | import org.junit.Before; |
---|
22 | import org.junit.BeforeClass; |
---|
23 | import org.junit.Test; |
---|
24 | import org.slf4j.Logger; |
---|
25 | import org.slf4j.LoggerFactory; |
---|
26 | import org.springframework.beans.factory.annotation.Autowired; |
---|
27 | import org.springframework.jdbc.core.JdbcTemplate; |
---|
28 | |
---|
29 | import static clarin.cmdi.componentregistry.rest.ComponentRegistryRestService.USERSPACE_PARAM; |
---|
30 | import static org.junit.Assert.*; |
---|
31 | |
---|
32 | /** |
---|
33 | * |
---|
34 | * @author george.georgovassilis@mpi.nl |
---|
35 | * |
---|
36 | */ |
---|
37 | public class ConcurrentRestServiceTest extends |
---|
38 | ComponentRegistryRestServiceTestCase { |
---|
39 | |
---|
40 | private final static Logger LOG = LoggerFactory |
---|
41 | .getLogger(ConcurrentRestServiceTest.class); |
---|
42 | private final int NR_OF_PROFILES = 20; |
---|
43 | private final int NR_OF_COMPONENTS = 20; |
---|
44 | |
---|
45 | @Autowired |
---|
46 | private JdbcTemplate jdbcTemplate; |
---|
47 | |
---|
48 | |
---|
49 | @Before |
---|
50 | public void init() { |
---|
51 | ComponentRegistryTestDatabase.resetAndCreateAllTables(jdbcTemplate); |
---|
52 | createUserRecord(); |
---|
53 | } |
---|
54 | |
---|
55 | @Test |
---|
56 | public void testConcurrentRegisterProfile() throws Exception { |
---|
57 | List<String> errors = new ArrayList<String>(); |
---|
58 | List<Thread> ts = new ArrayList<Thread>(); |
---|
59 | |
---|
60 | registerProfiles(ts, NR_OF_PROFILES, errors, false); |
---|
61 | registerProfiles(ts, NR_OF_PROFILES, errors, true); |
---|
62 | |
---|
63 | registerComponents(ts, NR_OF_COMPONENTS, errors, false); |
---|
64 | registerComponents(ts, NR_OF_COMPONENTS, errors, true); |
---|
65 | runAllThreads(ts); |
---|
66 | if (errors.size() > 0) { |
---|
67 | System.out.println(Arrays.toString(errors.toArray())); |
---|
68 | for (String e : errors) |
---|
69 | System.err.println(e); |
---|
70 | fail(); |
---|
71 | } |
---|
72 | assertProfiles(NR_OF_PROFILES, false); |
---|
73 | assertProfiles(NR_OF_PROFILES, true); |
---|
74 | |
---|
75 | assertComponents(NR_OF_COMPONENTS, false); |
---|
76 | assertComponents(NR_OF_COMPONENTS, true); |
---|
77 | } |
---|
78 | |
---|
79 | private void assertProfiles(int nrOfProfiles, boolean userSpace) { |
---|
80 | List<ProfileDescription> response = getAuthenticatedResource( |
---|
81 | getResource().path("/registry/profiles").queryParam( |
---|
82 | USERSPACE_PARAM, "" + userSpace)).accept( |
---|
83 | MediaType.APPLICATION_XML).get(PROFILE_LIST_GENERICTYPE); |
---|
84 | Collections.sort(response, descriptionComparator); |
---|
85 | assertEquals("half should be deleted", nrOfProfiles / 2, |
---|
86 | response.size()); |
---|
87 | for (int i = 0; i < nrOfProfiles / 2; i++) { |
---|
88 | ProfileDescription desc = response.get(i); |
---|
89 | assertEquals("Test Profile" + (i * 2 + 1000), desc.getName()); |
---|
90 | assertEquals("Test Profile" + (i * 2 + 1000) + " Description", |
---|
91 | desc.getDescription()); |
---|
92 | } |
---|
93 | } |
---|
94 | |
---|
95 | private Comparator<BaseDescription> descriptionComparator = new Comparator<BaseDescription>() { |
---|
96 | |
---|
97 | @Override |
---|
98 | public int compare(BaseDescription o1, BaseDescription o2) { |
---|
99 | return o1.getName().compareTo(o2.getName()); |
---|
100 | } |
---|
101 | }; |
---|
102 | |
---|
103 | private void assertComponents(int nrOfComponents, boolean userSpace) { |
---|
104 | List<ComponentDescription> cResponse = getAuthenticatedResource( |
---|
105 | getResource().path("/registry/components").queryParam( |
---|
106 | USERSPACE_PARAM, "" + userSpace)).accept( |
---|
107 | MediaType.APPLICATION_XML).get(COMPONENT_LIST_GENERICTYPE); |
---|
108 | Collections.sort(cResponse, descriptionComparator); |
---|
109 | assertEquals("half should be deleted", nrOfComponents / 2, |
---|
110 | cResponse.size()); |
---|
111 | for (int i = 0; i < nrOfComponents / 2; i++) { |
---|
112 | ComponentDescription desc = cResponse.get(i); |
---|
113 | assertEquals("Test Component" + (i * 2 + 1000), desc.getName()); |
---|
114 | assertEquals("Test Component" + (i * 2 + 1000) + " Description", |
---|
115 | desc.getDescription()); |
---|
116 | } |
---|
117 | } |
---|
118 | |
---|
119 | private void runAllThreads(List<Thread> ts) throws InterruptedException { |
---|
120 | for (Thread thread : ts) { |
---|
121 | thread.start(); |
---|
122 | thread.join(10); |
---|
123 | } |
---|
124 | for (Thread thread : ts) { |
---|
125 | thread.join(); // Wait till all are finished |
---|
126 | } |
---|
127 | } |
---|
128 | |
---|
129 | private void registerProfiles(List<Thread> ts, int size, |
---|
130 | final List<String> errors, boolean userSpace) |
---|
131 | throws InterruptedException { |
---|
132 | for (int i = 0; i < size; i++) { |
---|
133 | final boolean shouldDelete = (i % 2) == 1; |
---|
134 | LOG.debug("Profile {} should be registered in {} and {}", |
---|
135 | new Object[] { i + 1000, |
---|
136 | userSpace ? "user space" : "public space", |
---|
137 | shouldDelete ? "ALSO DELETED" : "not deleted" }); |
---|
138 | Thread thread = createThread("/registry/profiles/", userSpace, |
---|
139 | "Test Profile" + (i + 1000), shouldDelete, |
---|
140 | RegistryTestHelper.getTestProfileContent(), errors); |
---|
141 | ts.add(thread); |
---|
142 | } |
---|
143 | } |
---|
144 | |
---|
145 | private void registerComponents(List<Thread> ts, int size, |
---|
146 | final List<String> errors, boolean userSpace) |
---|
147 | throws InterruptedException { |
---|
148 | for (int i = 0; i < size; i++) { |
---|
149 | final boolean shouldDelete = (i % 2) == 1; |
---|
150 | LOG.debug("Component {} should be registered in {} and {}", |
---|
151 | new Object[] { i + 1000, |
---|
152 | userSpace ? "user space" : "public space", |
---|
153 | shouldDelete ? "ALSO DELETED" : "not deleted" }); |
---|
154 | Thread thread = createThread("/registry/components/", userSpace, |
---|
155 | "Test Component" + (i + 1000), shouldDelete, |
---|
156 | RegistryTestHelper.getComponentTestContent(), errors); |
---|
157 | ts.add(thread); |
---|
158 | } |
---|
159 | } |
---|
160 | |
---|
161 | private Thread createThread(final String path, final boolean userSpace, |
---|
162 | final String name, final boolean alsoDelete, InputStream content, |
---|
163 | final List<String> errors) throws InterruptedException { |
---|
164 | final FormDataMultiPart form = new FormDataMultiPart(); |
---|
165 | form.field(IComponentRegistryRestService.DATA_FORM_FIELD, content, |
---|
166 | MediaType.APPLICATION_OCTET_STREAM_TYPE); |
---|
167 | form.field(IComponentRegistryRestService.NAME_FORM_FIELD, name); |
---|
168 | form.field(IComponentRegistryRestService.DESCRIPTION_FORM_FIELD, name |
---|
169 | + " Description"); |
---|
170 | Thread t = new Thread(new Runnable() { |
---|
171 | |
---|
172 | @Override |
---|
173 | public void run() { |
---|
174 | long timestamp=-System.currentTimeMillis(); |
---|
175 | try { |
---|
176 | // System.out.println("THREAD STARTED"+Thread.currentThread().getName()); |
---|
177 | RegisterResponse registerResponse = getAuthenticatedResource( |
---|
178 | getResource().path(path).queryParam( |
---|
179 | USERSPACE_PARAM, "" + userSpace)).type( |
---|
180 | MediaType.MULTIPART_FORM_DATA).post( |
---|
181 | RegisterResponse.class, form); |
---|
182 | if (!registerResponse.isRegistered()) { |
---|
183 | errors.add("Failed to register " |
---|
184 | + Arrays.toString(registerResponse.getErrors() |
---|
185 | .toArray())); |
---|
186 | } |
---|
187 | LOG.debug(">>>>>>>>>>>>>>>> [Thread " + hashCode() |
---|
188 | + "] REGISTERING DESCRIPTION " + name + " " |
---|
189 | + registerResponse.getDescription().getId() |
---|
190 | + (Boolean.valueOf(userSpace) ? " userspace" : "") |
---|
191 | + (alsoDelete ? " alsoDelete" : "")); |
---|
192 | if (alsoDelete) { |
---|
193 | LOG.debug(">>>>>>>>>>>>>>>> [Thread " |
---|
194 | + hashCode() |
---|
195 | + "] DELETING DESCRIPTION " |
---|
196 | + name |
---|
197 | + " " |
---|
198 | + registerResponse.getDescription().getId() |
---|
199 | + (Boolean.valueOf(userSpace) ? " userspace " |
---|
200 | : "") |
---|
201 | + (alsoDelete ? " alsoDelete" : "")); |
---|
202 | ClientResponse response = getAuthenticatedResource( |
---|
203 | getResource().path( |
---|
204 | path |
---|
205 | + registerResponse |
---|
206 | .getDescription() |
---|
207 | .getId()).queryParam( |
---|
208 | USERSPACE_PARAM, "" + userSpace)) |
---|
209 | .delete(ClientResponse.class); |
---|
210 | if (response.getStatus() != 200) { |
---|
211 | errors.add("Failed to delete " |
---|
212 | + registerResponse.getDescription()); |
---|
213 | } |
---|
214 | } |
---|
215 | // System.out.println("THREAD FINISHED"+Thread.currentThread().getName()); |
---|
216 | } finally { |
---|
217 | timestamp+=System.currentTimeMillis(); |
---|
218 | LOG.info(Thread.currentThread().getName()+" duration: "+timestamp+" ms"); |
---|
219 | } |
---|
220 | } |
---|
221 | }); |
---|
222 | return t; |
---|
223 | |
---|
224 | } |
---|
225 | } |
---|