Skip to content

Commit 117d51d

Browse files
committed
HSEARCH-3739 Add ThreadSpy to execute assertions on threads created by Hibernate Search
1 parent bb971d3 commit 117d51d

File tree

1 file changed

+106
-0
lines changed
  • util/internal/integrationtest/common/src/main/java/org/hibernate/search/util/impl/integrationtest/common/rule

1 file changed

+106
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Hibernate Search, full-text search for your domain model
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.search.util.impl.integrationtest.common.rule;
8+
9+
import java.util.ArrayList;
10+
import java.util.Collections;
11+
import java.util.List;
12+
import java.util.Locale;
13+
import java.util.concurrent.ThreadFactory;
14+
import java.util.stream.Collectors;
15+
16+
import org.hibernate.search.engine.cfg.spi.EngineSpiSettings;
17+
import org.hibernate.search.engine.environment.bean.BeanHolder;
18+
import org.hibernate.search.engine.environment.bean.BeanReference;
19+
import org.hibernate.search.engine.environment.thread.spi.ThreadProvider;
20+
21+
import org.junit.rules.TestRule;
22+
import org.junit.runner.Description;
23+
import org.junit.runners.model.Statement;
24+
25+
/**
26+
* Spy on the threads created by Hibernate Search.
27+
* <p>
28+
* To use this, configure a ThreadSpy instance as a {@code @Rule} in your test,
29+
* then set {@link EngineSpiSettings#THREAD_PROVIDER} to the result of {@link ThreadSpy#getThreadProvider()}
30+
* when starting Hibernate Search.
31+
*/
32+
public class ThreadSpy implements TestRule {
33+
private List<Thread> createdThreads = Collections.synchronizedList( new ArrayList<>() );
34+
35+
@Override
36+
public Statement apply(Statement base, Description description) {
37+
return new Statement() {
38+
@Override
39+
public void evaluate() throws Throwable {
40+
setup();
41+
try {
42+
base.evaluate();
43+
}
44+
finally {
45+
tearDown();
46+
}
47+
}
48+
};
49+
}
50+
51+
public BeanReference<ThreadProvider> getThreadProvider() {
52+
return beanResolver -> {
53+
BeanHolder<? extends ThreadProvider> delegateHolder =
54+
beanResolver.resolve( EngineSpiSettings.Defaults.THREAD_PROVIDER );
55+
SpyingThreadProvider spyingFactory = new SpyingThreadProvider( delegateHolder.get() );
56+
return BeanHolder.<ThreadProvider>of( spyingFactory )
57+
.withDependencyAutoClosing( delegateHolder );
58+
};
59+
}
60+
61+
public List<Thread> getCreatedThreads(String stringInName) {
62+
return createdThreads.stream()
63+
.filter( t -> t.getName().toLowerCase( Locale.ROOT ).contains( stringInName.toLowerCase( Locale.ROOT ) ) )
64+
.collect( Collectors.toList() );
65+
}
66+
67+
private void setup() {
68+
}
69+
70+
private void tearDown() {
71+
createdThreads.clear();
72+
}
73+
74+
private class SpyingThreadProvider implements ThreadProvider {
75+
private final ThreadProvider delegate;
76+
77+
private SpyingThreadProvider(ThreadProvider delegate) {
78+
this.delegate = delegate;
79+
}
80+
81+
@Override
82+
public String createThreadName(String prefix, int threadNumber) {
83+
return delegate.createThreadName( prefix, threadNumber );
84+
}
85+
86+
@Override
87+
public ThreadFactory createThreadFactory(String prefix) {
88+
return new SpyingThreadFactory( delegate.createThreadFactory( prefix ) );
89+
}
90+
}
91+
92+
private class SpyingThreadFactory implements ThreadFactory {
93+
private final ThreadFactory delegate;
94+
95+
SpyingThreadFactory(ThreadFactory delegate) {
96+
this.delegate = delegate;
97+
}
98+
99+
@Override
100+
public Thread newThread(Runnable r) {
101+
Thread thread = delegate.newThread( r );
102+
createdThreads.add( thread );
103+
return thread;
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)