forked from reactive-streams/reactive-streams-dotnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSubscriberBlackboxVerificationTest.cs
218 lines (183 loc) · 10.9 KB
/
SubscriberBlackboxVerificationTest.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System;
using NUnit.Framework;
using Reactive.Streams.TCK.Tests.Support;
namespace Reactive.Streams.TCK.Tests
{
/// <summary>
/// Validates that the TCK's <see cref="SubscriberBlackboxVerification{T}"/> fails with nice human readable errors.
/// >Important: Please note that all Publishers implemented in this file are *wrong*!
/// </summary>
[TestFixture]
public class SubscriberBlackboxVerificationTest : TCKVerificationSupport
{
[Test]
public void Required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest_shouldFailBy_notGettingRequestCall()
=> RequireTestFailure(
() => NoopSubscriberVerification().Required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest(),
"Did not receive expected `Request` call within");
[Test]
public void Required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest_shouldPass()
=> SimpleSubscriberVerification().Required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest();
[Test]
public void Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete_shouldFail_dueToCallingRequest()
{
ISubscription subscription = null;
var subscriber = new LamdaSubscriber<int?>(onSubscribe: sub => subscription = sub,
onComplete: () => subscription.Request(1));
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete(),
"Subscription.Request MUST NOT be called from Subscriber.OnComplete (Rule 2.3)!");
}
[Test]
public void Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete_shouldFail_dueToCallingCancel()
{
ISubscription subscription = null;
var subscriber = new LamdaSubscriber<int?>(onSubscribe: sub => subscription = sub,
onComplete: () => subscription.Cancel());
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete(),
"Subscription.Cancel MUST NOT be called from Subscriber.OnComplete (Rule 2.3)!");
}
[Test]
public void Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError_shouldFail_dueToCallingRequest()
{
ISubscription subscription = null;
var subscriber = new LamdaSubscriber<int?>(onSubscribe: sub => subscription = sub,
onError: _ => subscription.Request(1));
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError(),
"Subscription.Request MUST NOT be called from Subscriber.OnError (Rule 2.3)!");
}
[Test]
public void Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError_shouldFail_dueToCallingCancel()
{
ISubscription subscription = null;
var subscriber = new LamdaSubscriber<int?>(onSubscribe: sub => subscription = sub,
onError: _ => subscription.Cancel());
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError(),
"Subscription.Cancel MUST NOT be called from Subscriber.OnError (Rule 2.3)!");
}
[Test]
public void Required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal_shouldFail()
{
ISubscription subscription = null;
var subscriber = new LamdaSubscriber<int?>(onSubscribe: sub =>
{
subscription = sub;
sub.Request(1); // this is wrong, as one should always check if should accept or reject the subscription
});
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal(),
"illegally called `Subscription.Request(1)`");
}
[Test]
public void Required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall_shouldFail()
=> RequireTestFailure(
() => CustomSubscriberVerification(new LamdaSubscriber<int?>()).Required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall(),
"did not call `RegisterOnComplete()`");
[Test]
public void Required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall_shouldPass_withNoopSubscriber()
=> CustomSubscriberVerification(new LamdaSubscriber<int?>())
.Required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall();
[Test]
public void Required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall_shouldFail()
{
var subscriber = new LamdaSubscriber<int?>(onError: cause =>
{
// this is wrong in many ways (incl. spec violation), but aims to simulate user code which "blows up" when handling the onError signal
throw new Exception("Wrong, don't do this!", cause); // don't do this
});
var verification = CustomSubscriberVerification(subscriber);
RequireTestFailure(() => verification.Required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall(),
"Test Exception: Boom!"); // checks that the expected exception was delivered to onError, we don't expect anyone to implement onError so weirdly
}
[Test]
public void Required_spec213_blackbox_mustThrowNullPointerExceptionWhenParametersAreNull_mustFailOnIgnoredNull_onSubscribe()
=> RequireTestFailure(
() => CustomSubscriberVerification(new LamdaSubscriber<int?>()).Required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull(),
"OnSubscribe(null) did not throw ArgumentNullException");
[Test]
public void Required_spec213_blackbox_mustThrowNullPointerExceptionWhenParametersAreNull_mustFailOnIgnoredNull_onNext()
=> RequireTestFailure(
() => CustomSubscriberVerification(new LamdaSubscriber<int?>()).Required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull(),
"OnNext(null) did not throw ArgumentNullException");
[Test]
public void Required_spec213_blackbox_mustThrowNullPointerExceptionWhenParametersAreNull_mustIgnoreSpecForValueType_onNext()
=> RequireTestSkip(
() => SimpleSubscriberVerification().Required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull(),
"Can't verify behavior for value types");
[Test]
public void Required_spec213_blackbox_mustThrowNullPointerExceptionWhenParametersAreNull_mustFailOnIgnoredNull_onError()
=> RequireTestFailure(
() => CustomSubscriberVerification(new LamdaSubscriber<int?>()).Required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull(),
"OnError(null) did not throw ArgumentNullException");
// FAILING IMPLEMENTATIONS //
/// <summary>
/// Verification using a Subscriber that doesn't do anything on any of the callbacks
/// </summary>
private SubscriberBlackboxVerification<int> NoopSubscriberVerification()
=> new NoopBlackboxVerification(new TestEnvironment());
[TestFixture(Ignore = "Helper verification for single test")]
private sealed class NoopBlackboxVerification : SubscriberBlackboxVerification<int>
{
//Requirement for NUnit even if the tests are ignored
public NoopBlackboxVerification() : base(new TestEnvironment())
{
}
public NoopBlackboxVerification(TestEnvironment environment) : base(environment)
{
}
public override int CreateElement(int element) => element;
public override ISubscriber<int> CreateSubscriber() => new LamdaSubscriber<int>();
}
/// <summary>
/// Verification using a Subscriber that only calls 'Requests(1)' on 'OnSubscribe' and 'OnNext'
/// </summary>
private SubscriberBlackboxVerification<int> SimpleSubscriberVerification()
=> new SimpleBlackboxVerification(new TestEnvironment());
[TestFixture(Ignore = "Helper verification for single test")]
private sealed class SimpleBlackboxVerification : SubscriberBlackboxVerification<int>
{
//Requirement for NUnit even if the tests are ignored
public SimpleBlackboxVerification() : base(new TestEnvironment())
{
}
public SimpleBlackboxVerification(TestEnvironment environment) : base(environment)
{
}
public override int CreateElement(int element) => element;
public override ISubscriber<int> CreateSubscriber()
{
ISubscription sub = null;
return new LamdaSubscriber<int>(
onSubscribe: subscription =>
{
sub = subscription;
sub.Request(1);
},
onNext: _ => sub.Request(1));
}
}
/// <summary>
/// Custom Verification using given Subscriber
/// </summary>
private SubscriberBlackboxVerification<int?> CustomSubscriberVerification(ISubscriber<int?> subscriber)
=> new CustomBlackboxVerification(new TestEnvironment(), subscriber);
[TestFixture(Ignore = "Helper verification for single test")]
private sealed class CustomBlackboxVerification : SubscriberBlackboxVerification<int?>
{
private readonly ISubscriber<int?> _subscriber;
//Requirement for NUnit even if the tests are ignored
public CustomBlackboxVerification() : base(new TestEnvironment())
{
}
public CustomBlackboxVerification(TestEnvironment environment, ISubscriber<int?> subscriber) : base(environment)
{
_subscriber = subscriber;
}
public override int? CreateElement(int element) => element;
public override ISubscriber<int?> CreateSubscriber() => _subscriber;
}
}
}