forked from elaatifi/orika
-
Notifications
You must be signed in to change notification settings - Fork 268
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test for DefaultBoundMapperFacade race condition
- Loading branch information
Alexander Demukh
committed
Jun 27, 2020
1 parent
19ed073
commit 0af16e7
Showing
4 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
89 changes: 89 additions & 0 deletions
89
...va/ma/glasnost/orika/test/concurrency/DefaultBoundMapperFacadeConcurrentInitTestCase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package ma.glasnost.orika.test.concurrency; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.TimeoutException; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.IntStream; | ||
|
||
import com.google.common.collect.Lists; | ||
|
||
import org.junit.After; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import ma.glasnost.orika.MapperFacade; | ||
import ma.glasnost.orika.MapperFactory; | ||
import ma.glasnost.orika.test.MappingUtil; | ||
import ma.glasnost.orika.test.concurrency.model.ModelWithNestedObjDest; | ||
import ma.glasnost.orika.test.concurrency.model.ModelWithNestedObjSource; | ||
import ma.glasnost.orika.test.concurrency.model.NestedModel; | ||
|
||
/** | ||
* Checks that instantiation and cache inside of <{@link ma.glasnost.orika.impl.DefaultBoundMapperFacade} is thread safe. | ||
*/ | ||
public class DefaultBoundMapperFacadeConcurrentInitTestCase { | ||
|
||
private MapperFacade mapper; | ||
|
||
private int threads = 20; | ||
private ExecutorService executor; | ||
|
||
@Before | ||
public void setup() { | ||
MapperFactory factory = MappingUtil.getMapperFactory(); | ||
factory.classMap(ModelWithNestedObjSource.class, ModelWithNestedObjDest.class) | ||
.byDefault() | ||
.register(); | ||
|
||
mapper = factory.getMapperFacade(); | ||
|
||
executor = Executors.newFixedThreadPool(threads); | ||
} | ||
|
||
@After | ||
public void cleanup() { | ||
if (executor != null) { | ||
executor.shutdownNow(); | ||
} | ||
} | ||
|
||
@Test | ||
public void testCase() { | ||
CountDownLatch readyLatch = new CountDownLatch(threads); | ||
|
||
List<Future<?>> futures = IntStream.range(0, threads).mapToObj(i -> | ||
executor.submit(() -> { | ||
ModelWithNestedObjSource model = i % 2 == 0 | ||
? new ModelWithNestedObjSource(Lists.newArrayList(new NestedModel("str"))) | ||
: new ModelWithNestedObjSource(Lists.newArrayList(new NestedModel(1))); | ||
|
||
readyLatch.countDown(); | ||
try { | ||
if (readyLatch.await(1, TimeUnit.SECONDS)) { | ||
Assert.assertEquals(model.getValue(), mapper.map(model, ModelWithNestedObjDest.class).getValue()); | ||
} else { | ||
throw new RuntimeException("Latch timeout"); | ||
} | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} | ||
}) | ||
).collect(Collectors.toList()); | ||
|
||
// check that no exception thrown inside futures | ||
for (Future<?> future : futures) { | ||
try { | ||
future.get(1, TimeUnit.SECONDS); | ||
} catch (InterruptedException | ExecutionException | TimeoutException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
tests/src/main/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjDest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package ma.glasnost.orika.test.concurrency.model; | ||
|
||
import java.util.List; | ||
|
||
public class ModelWithNestedObjDest { | ||
|
||
private List<NestedModel> value; | ||
|
||
public List<NestedModel> getValue() { | ||
return value; | ||
} | ||
|
||
public void setValue(List<NestedModel> value) { | ||
this.value = value; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
tests/src/main/java/ma/glasnost/orika/test/concurrency/model/ModelWithNestedObjSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package ma.glasnost.orika.test.concurrency.model; | ||
|
||
import java.util.List; | ||
|
||
public class ModelWithNestedObjSource { | ||
|
||
private List<NestedModel> value; | ||
|
||
public ModelWithNestedObjSource(List<NestedModel> value) { | ||
this.value = value; | ||
} | ||
|
||
public List<NestedModel> getValue() { | ||
return value; | ||
} | ||
|
||
public void setValue(List<NestedModel> value) { | ||
this.value = value; | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
tests/src/main/java/ma/glasnost/orika/test/concurrency/model/NestedModel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package ma.glasnost.orika.test.concurrency.model; | ||
|
||
import java.util.Objects; | ||
|
||
public class NestedModel { | ||
|
||
private Object value; | ||
|
||
public NestedModel(Object value) { | ||
this.value = value; | ||
} | ||
|
||
public Object getValue() { | ||
return value; | ||
} | ||
|
||
public void setValue(Object value) { | ||
this.value = value; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(value); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) | ||
return true; | ||
if (obj == null) | ||
return false; | ||
if (getClass() != obj.getClass()) | ||
return false; | ||
NestedModel other = (NestedModel) obj; | ||
return Objects.equals(value, other.value); | ||
} | ||
|
||
} |