Skip to content

Commit ca4fbeb

Browse files
authored
Channel reference in the ClosedChannel (#88)
1 parent c874a2d commit ca4fbeb

File tree

13 files changed

+54
-30
lines changed

13 files changed

+54
-30
lines changed

channel-ops/src/test/java/com/softwaremill/jox/ops/SourceOpsCollectTest.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.junit.jupiter.api.Test;
88

99
import static org.junit.jupiter.api.Assertions.assertEquals;
10+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
1011

1112
public class SourceOpsCollectTest {
1213
@Test
@@ -26,7 +27,7 @@ void testMapOverSource() throws Exception {
2627
assertEquals(10, s.receive());
2728
assertEquals(20, s.receive());
2829
assertEquals(30, s.receive());
29-
assertEquals(new ChannelDone(), s.receiveOrClosed());
30+
assertInstanceOf(ChannelDone.class, s.receiveOrClosed());
3031
return null;
3132
});
3233
}
@@ -52,7 +53,7 @@ void testCollectOverSource() throws Exception {
5253

5354
assertEquals(20, s.receive());
5455
assertEquals(40, s.receive());
55-
assertEquals(new ChannelDone(), s.receiveOrClosed());
56+
assertInstanceOf(ChannelDone.class, s.receiveOrClosed());
5657
return null;
5758
});
5859
}
@@ -71,7 +72,7 @@ void testCollectOverSourceStressTest() throws Exception {
7172
Source<Integer> s = SourceOps.forSource(scope, c).collect(x -> x * 10).toSource();
7273

7374
assertEquals(10, s.receive());
74-
assertEquals(new ChannelDone(), s.receiveOrClosed());
75+
assertInstanceOf(ChannelDone.class, s.receiveOrClosed());
7576
return null;
7677
});
7778
}
@@ -94,7 +95,7 @@ void testCollectOverSourceUsingForSyntax() throws Exception {
9495
assertEquals(2, s.receive());
9596
assertEquals(4, s.receive());
9697
assertEquals(6, s.receive());
97-
assertEquals(new ChannelDone(), s.receiveOrClosed());
98+
assertInstanceOf(ChannelDone.class, s.receiveOrClosed());
9899
return null;
99100
});
100101
}

channels/src/main/java/com/softwaremill/jox/Channel.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ public void done() {
706706

707707
@Override
708708
public Object doneOrClosed() {
709-
return closeOrClosed(new ChannelDone());
709+
return closeOrClosed(new ChannelDone(this));
710710
}
711711

712712
@Override
@@ -722,7 +722,7 @@ public void error(Throwable reason) {
722722

723723
@Override
724724
public Object errorOrClosed(Throwable reason) {
725-
return closeOrClosed(new ChannelError(reason));
725+
return closeOrClosed(new ChannelError(reason, this));
726726
}
727727

728728
private Object closeOrClosed(ChannelClosed channelClosed) {

channels/src/main/java/com/softwaremill/jox/ChannelClosed.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
*/
66
public sealed interface ChannelClosed permits ChannelDone, ChannelError {
77
ChannelClosedException toException();
8+
Channel<?> channel();
89
}

channels/src/main/java/com/softwaremill/jox/ChannelDone.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.softwaremill.jox;
22

3-
public record ChannelDone() implements ChannelClosed {
3+
public record ChannelDone(Channel<?> channel) implements ChannelClosed {
44
@Override
55
public ChannelClosedException toException() {
66
return new ChannelDoneException();

channels/src/main/java/com/softwaremill/jox/ChannelError.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.softwaremill.jox;
22

3-
public record ChannelError(Throwable cause) implements ChannelClosed {
3+
public record ChannelError(Throwable cause, Channel<?> channel) implements ChannelClosed {
44
@Override
55
public ChannelClosedException toException() {
66
return new ChannelErrorException(cause);

channels/src/main/java/com/softwaremill/jox/Select.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ public class Select {
4848
* <p>
4949
* If no clauses are given, throws {@link ChannelDoneException}.
5050
*
51-
* @param clauses The clauses, from which one will be selected. Not {@code null}.
51+
* @param clauses The clauses, from which one will be selected. Array must not be empty or {@code null} and
52+
* can't contain {@code null} values.
5253
* @return The value returned by the selected clause.
5354
* @throws ChannelClosedException When any of the channels is closed (done or in error).
5455
*/
@@ -72,16 +73,21 @@ public static <U> U select(SelectClause<? extends U>... clauses) throws Interrup
7273
* <p>
7374
* If no clauses are given, returns {@link ChannelDone}.
7475
*
75-
* @param clauses The clauses, from which one will be selected. Not {@code null}.
76+
* @param clauses The clauses, from which one will be selected. Array must not be empty or {@code null} and
77+
* can't contain {@code null} values.
7678
* @return Either the value returned by the selected clause, or {@link ChannelClosed}, when any of the channels
7779
* is closed (done or in error).
7880
*/
7981
@SafeVarargs
8082
public static <U> Object selectOrClosed(SelectClause<? extends U>... clauses) throws InterruptedException {
8183
while (true) {
82-
if (clauses.length == 0) {
84+
if (clauses == null || clauses.length == 0) {
8385
// no clauses given
84-
return new ChannelDone();
86+
throw new IllegalArgumentException("No clauses given");
87+
}
88+
if (Arrays.stream(clauses).anyMatch(Objects::isNull)){
89+
// null clauses given
90+
throw new IllegalArgumentException("Null clauses are not supported");
8591
}
8692

8793
var r = doSelectOrClosed(clauses);

channels/src/test/java/com/softwaremill/jox/ChannelClosedTest.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,29 @@
33
import org.junit.jupiter.api.Test;
44

55
import java.util.concurrent.ExecutionException;
6-
import java.util.concurrent.Future;
7-
import java.util.concurrent.Semaphore;
86

9-
import static com.softwaremill.jox.TestUtil.*;
7+
import static com.softwaremill.jox.TestUtil.forkCancelable;
8+
import static com.softwaremill.jox.TestUtil.scoped;
109
import static org.junit.jupiter.api.Assertions.*;
1110

1211
public class ChannelClosedTest {
1312
@Test
14-
void testClosed_noValues_whenError() {
13+
void testClosed_noValues_whenError() throws InterruptedException {
1514
// given
1615
Channel<Integer> c = new Channel<>();
16+
RuntimeException reason = new RuntimeException();
1717

1818
// when
19-
c.error(new RuntimeException());
19+
c.error(reason);
2020

2121
// then
2222
assertTrue(c.isClosedForReceive());
2323
assertTrue(c.isClosedForSend());
24+
assertEquals(new ChannelError(reason, c), c.receiveOrClosed());
2425
}
2526

2627
@Test
27-
void testClosed_noValues_whenDone() {
28+
void testClosed_noValues_whenDone() throws InterruptedException {
2829
// given
2930
Channel<Integer> c = new Channel<>();
3031

@@ -34,6 +35,7 @@ void testClosed_noValues_whenDone() {
3435
// then
3536
assertTrue(c.isClosedForReceive());
3637
assertTrue(c.isClosedForSend());
38+
assertEquals(new ChannelDone(c), c.receiveOrClosed());
3739
}
3840

3941
@Test

channels/src/test/java/com/softwaremill/jox/ChannelRendezvousTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ void pendingReceivesShouldGetNotifiedThatChannelIsDone() throws InterruptedExcep
121121
c.done();
122122

123123
// then
124-
assertEquals(new ChannelDone(), f.get());
124+
assertEquals(new ChannelDone(c), f.get());
125125

126126
// should be rejected immediately
127-
assertEquals(new ChannelDone(), c.receiveOrClosed());
127+
assertEquals(new ChannelDone(c), c.receiveOrClosed());
128128
});
129129
}
130130

channels/src/test/java/com/softwaremill/jox/SelectReceiveTest.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import static com.softwaremill.jox.Select.selectOrClosed;
1111
import static com.softwaremill.jox.TestUtil.*;
1212
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.junit.jupiter.api.Assertions.assertThrows;
1314

1415
public class SelectReceiveTest {
1516
@Test
@@ -139,7 +140,7 @@ void testSelectWhenDone() throws InterruptedException {
139140
Object received = selectOrClosed(ch1.receiveClause(), ch2.receiveClause());
140141

141142
// then
142-
assertEquals(new ChannelDone(), received);
143+
assertEquals(new ChannelDone(ch1), received);
143144
}
144145

145146
@TestWithCapacities
@@ -219,12 +220,24 @@ void testBufferExpandedWhenSelecting() throws InterruptedException {
219220
}
220221

221222
@Test
222-
void testSelectFromNone() throws InterruptedException {
223-
assertEquals(new ChannelDone(), selectOrClosed());
223+
void testSelectFromNone() {
224+
assertThrows(IllegalArgumentException.class, Select::selectOrClosed);
224225
}
225226

226227
@Test
227-
public void testSelect_immediate_withError() throws InterruptedException {
228+
void testSelectFromNullableList() throws InterruptedException {
229+
// given
230+
Channel<String> ch1 = new Channel<>(1);
231+
Channel<String> ch2 = new Channel<>(1);
232+
ch1.send("v");
233+
234+
// when
235+
assertThrows(IllegalArgumentException.class,
236+
() -> select(ch1.receiveClause(), null, ch2.receiveClause()));
237+
}
238+
239+
@Test
240+
void testSelect_immediate_withError() throws InterruptedException {
228241
// given
229242
Channel<String> ch1 = new Channel<>(2);
230243
ch1.send("x");
@@ -237,6 +250,6 @@ public void testSelect_immediate_withError() throws InterruptedException {
237250
var result = selectOrClosed(ch1.receiveClause(), ch2.receiveClause());
238251

239252
// then
240-
assertEquals(new ChannelError(e), result);
253+
assertEquals(new ChannelError(e, ch2), result);
241254
}
242255
}

channels/src/test/java/com/softwaremill/jox/SelectSendTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public void testSelectWhenDone() throws InterruptedException {
107107
Object received = selectOrClosed(ch1.sendClause("v1"), ch2.sendClause("v2"));
108108

109109
// then
110-
assertEquals(new ChannelDone(), received);
110+
assertEquals(new ChannelDone(ch2), received);
111111
}
112112

113113
@TestWithCapacities

0 commit comments

Comments
 (0)