Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5b2d748

Browse files
committedOct 27, 2017
Testing
- Removed Cucumber + Add unit tests (not the best and sometimes fail because threading but will work for now) * TODO: Redocument methods as a few have changed and a number were never documented in the first place
1 parent 9f8326e commit 5b2d748

15 files changed

+410
-278
lines changed
 

‎build.gradle

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
apply plugin: 'java-library'
22
apply plugin: 'eclipse'
33

4-
version = '0.5.0'
4+
version = '0.6.0'
55

66
// Repositories, where to find dependencies
77
repositories {
8-
jcenter()
8+
jcenter()
99
}
1010

1111
// Dependencies
1212
dependencies {
1313

14-
// The production code uses the SLF4J logging API at compile time
15-
implementation 'org.slf4j:slf4j-api:1.7.21'
14+
// The production code uses the SLF4J logging API at compile time
15+
implementation 'org.slf4j:slf4j-api:1.7.21'
1616

1717
// Caffeine high performance cache library
1818
implementation 'com.github.ben-manes.caffeine:caffeine:2.4.0'
1919

20-
// Testing stuff
21-
testImplementation 'junit:junit:4.12'
22-
testImplementation 'info.cukes:cucumber-junit:1.2.5'
23-
testImplementation 'info.cukes:cucumber-java:1.2.5'
20+
// Testing stuff
21+
testImplementation 'junit:junit:4.12'
2422
}
2523

2624
task wrapper(type: Wrapper) {
27-
gradleVersion = '4.2.1'
25+
gradleVersion = '4.2.1'
2826
}

‎settings.gradle

-18
Original file line numberDiff line numberDiff line change
@@ -1,19 +1 @@
1-
/*
2-
* This settings file was auto generated by the Gradle buildInit task
3-
* by 'Josh' at '1/19/17 9:12 AM' with Gradle 2.14.1
4-
*
5-
* The settings file is used to specify which projects to include in your build.
6-
* In a single project build this file can be empty or even removed.
7-
*
8-
* Detailed information about configuring a multi-project build in Gradle can be found
9-
* in the user guide at https://docs.gradle.org/2.14.1/userguide/multi_project_builds.html
10-
*/
11-
12-
/*
13-
// To declare projects as part of a multi-project build use the 'include' method
14-
include 'shared'
15-
include 'api'
16-
include 'services:webservice'
17-
*/
18-
191
rootProject.name = 'Themis'

‎src/main/java/com/shadowcs/themis/EventManager.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public EventManager(ExecutorService eService) {
2626
}
2727

2828
public <V> EventManager addListener(Consumer<V> listener, Class<V> klass) {
29-
lCache.get(klass).add(listener);
29+
if(listener != null && klass != null) {
30+
lCache.get(klass).add(listener);
31+
}
3032
return this;
3133
}
3234

‎src/main/java/com/shadowcs/themis/util/concurrent/ProcedureThreadFactory.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929
public class ProcedureThreadFactory extends DefaultThreadFactory {
3030

3131
private Runnable procedure;
32+
33+
public ProcedureThreadFactory() {
34+
this(null);
35+
}
3236

3337
public ProcedureThreadFactory(Runnable procedure) {
34-
super();
3538
this.procedure = procedure;
3639
}
3740

@@ -40,7 +43,9 @@ public Thread newThread(Runnable r) {
4043
if(procedure != null) {
4144
procedure.run();
4245
}
43-
r.run();
46+
if(r != null) {
47+
r.run();
48+
}
4449
});
4550
}
4651
}

‎src/main/java/com/shadowcs/themis/util/concurrent/ProvidedThreadFactory.java

+18-30
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.concurrent.LinkedBlockingQueue;
2424
import java.util.concurrent.Semaphore;
2525
import java.util.concurrent.ThreadFactory;
26-
import java.util.concurrent.atomic.AtomicInteger;
2726

2827
/**
2928
* An object that takes already started and provided threads and allows them to be used as part of a thread pool without
@@ -38,16 +37,17 @@
3837
*/
3938
public class ProvidedThreadFactory implements ThreadFactory, AutoCloseable {
4039

41-
private AtomicInteger count = new AtomicInteger();
42-
private Queue<ThreadWork> queue = new LinkedBlockingQueue<ThreadWork>();
40+
private volatile Queue<ThreadWork> queue = new LinkedBlockingQueue<ThreadWork>();
41+
private volatile Queue<ThreadWork> workQueue = queue;
4342

4443
public ProvidedThreadFactory() {
4544

4645
}
4746

47+
// TODO: document and maybe throw Interrupt as a different type?
4848
// just a cleaner cede
4949
public void cede() {
50-
cede(null); // does nothing
50+
cede(null);
5151
}
5252

5353
/**
@@ -63,45 +63,31 @@ public void cede() {
6363
* @throws InterruptedException
6464
*/
6565
public void cede(Runnable procedure) {
66-
count.incrementAndGet();
66+
6767
ThreadWork work = new ThreadWork();
68-
if(queue.offer(work)) {
69-
if(procedure != null) {
70-
new Thread(procedure, "procedure-cede").start(); // TODO: probably not name the thread
68+
new Thread(procedure).start();
69+
70+
while(queue != null && queue.offer(work)) {
71+
try {
72+
work.await();
73+
} catch(InterruptedException e) {
74+
return;
7175
}
72-
73-
do {
74-
try {
75-
work.await();
76-
} catch(InterruptedException e) {
77-
// Thread interrupted so we simply leave
78-
// This is expected to be proper behavior
79-
// e.printStackTrace();
80-
count.decrementAndGet();
81-
return;
82-
}
83-
} while(queue.offer(work));
8476
}
85-
86-
count.decrementAndGet();
87-
throw new RuntimeException("Failed to cede/recycle thread!");
8877
}
8978

9079
public Thread newThread(Runnable r) {
91-
ThreadWork work = queue.poll();
80+
ThreadWork work = workQueue.poll();
9281
if(work != null) { return new Thread(() -> work.submit(r)); }
9382

9483
return null;
9584
}
9685

9786
@Override
9887
public void close() {
99-
Runnable work = () -> Thread.currentThread().interrupt();
10088

101-
// I might not need count but it works well for now
102-
for(int i = 0; i < count.get(); i++) {
103-
newThread(work).start();
104-
}
89+
queue = null;
90+
workQueue.forEach(work -> work.submit(null));
10591
}
10692

10793
private class ThreadWork {
@@ -115,7 +101,9 @@ public ThreadWork() {
115101

116102
public void await() throws InterruptedException {
117103
sema.acquire();
118-
rWork.run();
104+
if(rWork != null) {
105+
rWork.run();
106+
}
119107
}
120108

121109
public void submit(Runnable r) {

‎src/main/java/com/shadowcs/themis/util/concurrent/package-info.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020

2121
/**
22-
* Utility classes useful in assisting with the concurrent nature of the event framwork.
22+
* Utility classes useful in assisting with the concurrent nature of the event framework.
2323
*
2424
* @author Josh "ShadowLordAlpha"
2525
*/

‎src/test/java/com/shadowcs/themis/test/CucumberRunner.java

-9
This file was deleted.

‎src/test/java/com/shadowcs/themis/test/CucumberStepDef.java

-110
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.shadowcs.themis.test;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import java.util.concurrent.ThreadFactory;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import org.junit.Test;
7+
import com.shadowcs.themis.util.concurrent.DefaultThreadFactory;
8+
import com.shadowcs.themis.util.concurrent.SimpleThreadFactory;
9+
10+
11+
public class DefaultThreadFactoryTest {
12+
13+
@Test
14+
public void objectCreation() {
15+
new SimpleThreadFactory();
16+
}
17+
18+
@Test
19+
public void threadCreation() throws InterruptedException {
20+
21+
ThreadFactory sThreadFactory = new DefaultThreadFactory();
22+
for(int i = 0; i < 100; i++) {
23+
Thread t = sThreadFactory.newThread(null);
24+
t.start();
25+
t.join(1000);
26+
}
27+
}
28+
29+
@Test
30+
public void threadWork() throws InterruptedException {
31+
32+
AtomicInteger integer = new AtomicInteger();
33+
34+
ThreadFactory sThreadFactory = new DefaultThreadFactory();
35+
for(int i = 0; i < 100; i++) {
36+
Thread t = sThreadFactory.newThread(() -> integer.incrementAndGet());
37+
t.start();
38+
t.join(1000);
39+
}
40+
41+
assertEquals(100, integer.get());
42+
}
43+
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.shadowcs.themis.test;
2+
3+
import static org.junit.Assert.*;
4+
import java.util.concurrent.ExecutionException;
5+
import java.util.concurrent.ThreadFactory;
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
import org.junit.Test;
8+
import com.shadowcs.themis.EventManager;
9+
import com.shadowcs.themis.util.concurrent.SimpleThreadFactory;
10+
11+
12+
public class EventManagerTest {
13+
14+
@Test
15+
public void objectCreation() {
16+
new EventManager().close();;
17+
}
18+
19+
@Test
20+
public void threadCreationNull() throws InterruptedException {
21+
22+
AtomicInteger integer = new AtomicInteger();
23+
24+
EventManager eventManager = new EventManager();
25+
eventManager.addListener(null, Runnable.class);
26+
for(int i = 0; i < 100; i++) {
27+
eventManager.execute((Runnable) () -> integer.incrementAndGet());
28+
}
29+
30+
for(int i = 0; i < 100; i++) {
31+
try {
32+
eventManager.submit((Runnable) () -> integer.incrementAndGet()).get();
33+
} catch(ExecutionException e) {
34+
e.printStackTrace();
35+
}
36+
}
37+
38+
for(int i = 0; i < 100; i++) {
39+
eventManager.invoke((Runnable) () -> integer.incrementAndGet());
40+
}
41+
42+
assertEquals(0, integer.get());
43+
}
44+
45+
@Test
46+
public void threadCreationListener() throws InterruptedException {
47+
48+
AtomicInteger integer = new AtomicInteger();
49+
AtomicInteger expected = new AtomicInteger();
50+
51+
EventManager eventManager = new EventManager();
52+
eventManager.addListener((run) -> run.run(), Runnable.class);
53+
for(int i = 0; i < 100; i++) {
54+
expected.incrementAndGet();
55+
eventManager.execute((Runnable) () -> integer.incrementAndGet());
56+
}
57+
58+
for(int i = 0; i < 100; i++) {
59+
try {
60+
expected.incrementAndGet();
61+
eventManager.submit((Runnable) () -> integer.incrementAndGet()).get();
62+
} catch(ExecutionException e) {
63+
// TODO Auto-generated catch block
64+
e.printStackTrace();
65+
}
66+
}
67+
68+
for(int i = 0; i < 100; i++) {
69+
expected.incrementAndGet();
70+
eventManager.invoke((Runnable) () -> integer.incrementAndGet());
71+
}
72+
73+
assertEquals(300, integer.get());
74+
}
75+
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.shadowcs.themis.test;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import java.util.concurrent.ThreadFactory;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import org.junit.Test;
7+
import com.shadowcs.themis.util.concurrent.ProcedureThreadFactory;
8+
import com.shadowcs.themis.util.concurrent.SimpleThreadFactory;
9+
10+
11+
public class ProcedureThreadFactoryTest {
12+
13+
@Test
14+
public void objectCreation() {
15+
new SimpleThreadFactory();
16+
}
17+
18+
@Test
19+
public void threadCreationNull() throws InterruptedException {
20+
21+
ThreadFactory sThreadFactory = new ProcedureThreadFactory();
22+
for(int i = 0; i < 100; i++) {
23+
Thread t = sThreadFactory.newThread(null);
24+
t.start();
25+
t.join(1000);
26+
}
27+
}
28+
29+
@Test
30+
public void threadCreationProc() throws InterruptedException {
31+
32+
// TODO: text output is not the best testing
33+
ThreadFactory sThreadFactory = new ProcedureThreadFactory(() -> System.out.println("Proc run"));
34+
for(int i = 0; i < 100; i++) {
35+
Thread t = sThreadFactory.newThread(null);
36+
t.start();
37+
t.join(1000);
38+
}
39+
}
40+
41+
@Test
42+
public void threadWork() throws InterruptedException {
43+
44+
AtomicInteger integer = new AtomicInteger();
45+
46+
ThreadFactory sThreadFactory = new ProcedureThreadFactory();
47+
for(int i = 0; i < 100; i++) {
48+
Thread t = sThreadFactory.newThread(() -> integer.incrementAndGet());
49+
t.start();
50+
t.join(1000);
51+
}
52+
53+
assertEquals(100, integer.get());
54+
}
55+
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package com.shadowcs.themis.test;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertTrue;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import org.junit.Test;
7+
import com.shadowcs.themis.util.concurrent.ProvidedThreadFactory;
8+
9+
public class ProvidedThreadFactoryTest {
10+
11+
@Test
12+
public void objectCreation() {
13+
new ProvidedThreadFactory().close();
14+
}
15+
16+
@Test
17+
public void threadCreationBlank() throws InterruptedException {
18+
19+
ProvidedThreadFactory pThreadFactory = new ProvidedThreadFactory();
20+
new Thread(() -> pThreadFactory.cede()).start();
21+
Thread.sleep(1000);
22+
for(int i = 0; i < 100; i++) {
23+
Thread t = pThreadFactory.newThread(null);
24+
if(t != null) {
25+
t.start();
26+
t.join();
27+
}
28+
}
29+
30+
pThreadFactory.close();
31+
}
32+
33+
@Test
34+
public void threadCreationCede() throws InterruptedException {
35+
36+
ProvidedThreadFactory pThreadFactory = new ProvidedThreadFactory();
37+
new Thread(() -> pThreadFactory.cede(() -> System.out.println("Test"))).start(); // TODO: replace this with a boolean or something
38+
Thread.sleep(500); // sleeps are bad for tests but I can't think of a better way atm
39+
for(int i = 0; i < 100; i++) {
40+
Thread t = pThreadFactory.newThread(null);
41+
if(t != null) {
42+
t.start();
43+
t.join();
44+
}
45+
}
46+
47+
Thread.sleep(500);
48+
pThreadFactory.close();
49+
}
50+
51+
@Test
52+
public void threadWorkSingle() throws InterruptedException {
53+
54+
AtomicInteger expected = new AtomicInteger();
55+
AtomicInteger integer = new AtomicInteger();
56+
57+
ProvidedThreadFactory pThreadFactory = new ProvidedThreadFactory();
58+
Thread thread = new Thread(() -> pThreadFactory.cede());
59+
thread.start();
60+
61+
Thread.sleep(500); // TODO: this one is an even worse test
62+
63+
for(int i = 0; i < 100; i++) {
64+
Thread t = pThreadFactory.newThread(() -> integer.incrementAndGet());
65+
if(t != null) {
66+
expected.incrementAndGet();
67+
t.start();
68+
}
69+
}
70+
71+
Thread.sleep(500);
72+
pThreadFactory.close();
73+
thread.join();
74+
75+
System.out.println(expected.get());
76+
assertEquals(expected.get(), integer.get());
77+
}
78+
79+
@Test
80+
public void threadWorkInterrupt() throws InterruptedException {
81+
82+
ProvidedThreadFactory pThreadFactory = new ProvidedThreadFactory();
83+
Thread thread = new Thread(() -> pThreadFactory.cede());
84+
thread.start();
85+
86+
Thread.sleep(500); // TODO: this one is an even worse test
87+
88+
for(int i = 0; i < 100; i++) {
89+
Thread t = pThreadFactory.newThread(() -> {
90+
91+
Thread.currentThread().interrupt();
92+
});
93+
94+
if(t != null) {
95+
t.start();
96+
}
97+
}
98+
99+
thread.join(5000);
100+
pThreadFactory.close();
101+
}
102+
103+
@Test
104+
public void threadWorkMulti() throws InterruptedException {
105+
106+
AtomicInteger expected = new AtomicInteger();
107+
AtomicInteger integer = new AtomicInteger();
108+
109+
ProvidedThreadFactory pThreadFactory = new ProvidedThreadFactory();
110+
Thread thread0 = new Thread(() -> pThreadFactory.cede());
111+
Thread thread1 = new Thread(() -> pThreadFactory.cede());
112+
Thread thread2 = new Thread(() -> pThreadFactory.cede());
113+
Thread thread3 = new Thread(() -> pThreadFactory.cede());
114+
Thread thread4 = new Thread(() -> pThreadFactory.cede());
115+
Thread thread5 = new Thread(() -> pThreadFactory.cede());
116+
Thread thread6 = new Thread(() -> pThreadFactory.cede());
117+
Thread thread7 = new Thread(() -> pThreadFactory.cede());
118+
Thread thread8 = new Thread(() -> pThreadFactory.cede());
119+
Thread thread9 = new Thread(() -> pThreadFactory.cede());
120+
thread0.start();
121+
thread1.start();
122+
thread2.start();
123+
thread3.start();
124+
thread4.start();
125+
thread5.start();
126+
thread6.start();
127+
thread7.start();
128+
thread8.start();
129+
thread9.start();
130+
131+
for(int i = 0; i < 100; i++) {
132+
Thread t = pThreadFactory.newThread(() -> integer.incrementAndGet());
133+
if(t != null) {
134+
expected.incrementAndGet();
135+
t.start();
136+
}
137+
}
138+
139+
pThreadFactory.close();
140+
thread0.join();
141+
thread1.join();
142+
thread2.join();
143+
thread3.join();
144+
thread4.join();
145+
thread5.join();
146+
thread6.join();
147+
thread7.join();
148+
thread8.join();
149+
thread9.join(); // need to find a better way than this
150+
151+
System.out.println(expected.get());
152+
assertTrue(expected.get() > 0); // TODO: need a better way than this
153+
assertEquals(expected.get(), integer.get());
154+
}
155+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.shadowcs.themis.test;
2+
3+
import static org.junit.Assert.*;
4+
import java.util.concurrent.ThreadFactory;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import org.junit.Test;
7+
import com.shadowcs.themis.util.concurrent.SimpleThreadFactory;
8+
9+
10+
public class SimpleThreadFactoryTest {
11+
12+
@Test
13+
public void objectCreation() {
14+
new SimpleThreadFactory();
15+
}
16+
17+
@Test
18+
public void threadCreation() throws InterruptedException {
19+
20+
ThreadFactory sThreadFactory = new SimpleThreadFactory();
21+
for(int i = 0; i < 100; i++) {
22+
Thread t = sThreadFactory.newThread(null);
23+
t.start();
24+
t.join(1000);
25+
}
26+
}
27+
28+
@Test
29+
public void threadWork() throws InterruptedException {
30+
31+
AtomicInteger integer = new AtomicInteger();
32+
33+
ThreadFactory sThreadFactory = new SimpleThreadFactory();
34+
for(int i = 0; i < 100; i++) {
35+
Thread t = sThreadFactory.newThread(() -> integer.incrementAndGet());
36+
t.start();
37+
t.join(1000);
38+
}
39+
40+
assertEquals(100, integer.get());
41+
}
42+
43+
}

‎src/test/resources/com/shadowcs/themis/test/EventManager.feature

Whitespace-only changes.

‎src/test/resources/com/shadowcs/themis/test/ThreadFactory.feature

-98
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.