Skip to content

Commit 4b06168

Browse files
Updated subject in fallback handler (#358)
* Updated subject in fallback handler * Added testing util to replace Task.Delay() * fix progress tests * Updated dynamic registration tests
1 parent b0ae859 commit 4b06168

14 files changed

+142
-67
lines changed

src/Protocol/LanguageProtocolDelegatingHandlers.cs

+8
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ CancellationToken cancellationToken
400400
}
401401

402402
var subject = new AsyncSubject<TItem>();
403+
// in the event nothing is emitted...
404+
subject.OnNext(default);
403405
_handler(request, subject, _capability, cancellationToken);
404406
return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false);
405407
}
@@ -468,6 +470,8 @@ async Task<TResponse> IRequestHandler<TParams, TResponse>.Handle(TParams request
468470
}
469471

470472
var subject = new AsyncSubject<TItem>();
473+
// in the event nothing is emitted...
474+
subject.OnNext(default);
471475
_handler(request, subject, cancellationToken);
472476
return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false);
473477
}
@@ -528,6 +532,8 @@ async Task<TResponse> IRequestHandler<TParams, TResponse>.Handle(TParams request
528532
}
529533

530534
var subject = new AsyncSubject<TItem>();
535+
// in the event nothing is emitted...
536+
subject.OnNext(default);
531537
_handler(request, _capability, subject, cancellationToken);
532538
return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false);
533539
}
@@ -584,6 +590,8 @@ async Task<TResponse> IRequestHandler<TParams, TResponse>.Handle(TParams request
584590
}
585591

586592
var subject = new AsyncSubject<TItem>();
593+
// in the event nothing is emitted...
594+
subject.OnNext(default);
587595
_handler(request, subject, cancellationToken);
588596
return await subject.Select(_factory).ToTask(cancellationToken).ConfigureAwait(false);
589597
}

test/Dap.Tests/Integration/ProgressTests.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using OmniSharp.Extensions.DebugAdapter.Server;
1111
using OmniSharp.Extensions.DebugAdapter.Testing;
1212
using OmniSharp.Extensions.JsonRpc.Testing;
13+
using TestingUtils;
1314
using Xunit;
1415
using Xunit.Abstractions;
1516

@@ -75,7 +76,7 @@ public async Task Should_Support_Progress_From_Sever_To_Client()
7576
}
7677
);
7778

78-
await Task.Delay(1000);
79+
await data.DelayUntilCount(6, CancellationToken);
7980

8081
var results = data.Select(
8182
z => z switch {

test/Lsp.Tests/Integration/DynamicRegistrationTests.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities;
2222
using OmniSharp.Extensions.LanguageServer.Protocol.Shared;
2323
using OmniSharp.Extensions.LanguageServer.Server;
24+
using TestingUtils;
2425
using Xunit;
2526
using Xunit.Abstractions;
2627

@@ -124,7 +125,9 @@ public async Task Should_Unregister_Dynamically_While_Server_Is_Running()
124125
await WaitForRegistrationUpdate(client);
125126
disposable.Dispose();
126127
await WaitForRegistrationUpdate(client);
127-
await Task.Delay(1000);
128+
await TestHelper.DelayUntil(
129+
() => client.RegistrationManager.CurrentRegistrations, z => !SelectorMatches(z, x => x.HasLanguage && x.Language == "vb"), CancellationToken
130+
);
128131
}
129132

130133
client.RegistrationManager.CurrentRegistrations.Should().NotContain(

test/Lsp.Tests/Integration/LanguageServerConfigurationTests.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
1212
using OmniSharp.Extensions.LanguageServer.Server;
1313
using Serilog.Events;
14+
using TestingUtils;
1415
using Xunit;
1516
using Xunit.Abstractions;
1617

@@ -137,7 +138,7 @@ public async Task Should_Fallback_To_Original_Configuration()
137138
await scopedConfiguration.WaitForChange(CancellationToken);
138139
await SettleNext();
139140

140-
await Task.Delay(2000);
141+
await TestHelper.DelayUntil(() => scopedConfiguration["mysection:key"] == "value", CancellationToken);
141142

142143
scopedConfiguration["mysection:key"].Should().Be("value");
143144
scopedConfiguration["othersection:value"].Should().Be("key");

test/Lsp.Tests/Integration/LanguageServerLoggingTests.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
1414
using OmniSharp.Extensions.LanguageServer.Server;
1515
using Serilog.Events;
16+
using TestingUtils;
1617
using Xunit;
1718
using Xunit.Abstractions;
1819

@@ -53,7 +54,7 @@ public async Task Logs_Are_Sent_To_Client_From_Server()
5354
logger.LogTrace("Just gotta let you trace!");
5455
logger.LogDebug("Just gotta let you debug!");
5556

56-
await Task.Delay(1000);
57+
await _logs.DelayUntilCount(6, CancellationToken);
5758

5859
_logs.Should().HaveCount(6);
5960
_logs.Where(z => z.Type == MessageType.Error).Should().HaveCount(2);
@@ -89,7 +90,7 @@ public async Task Logs_Are_Sent_To_Client_From_Server_Respecting_SetMinimumLevel
8990
logger.LogTrace("Just gotta let you trace!");
9091
logger.LogDebug("Just gotta let you debug!");
9192

92-
await Task.Delay(1000);
93+
await _logs.DelayUntilCount(3, CancellationToken);
9394

9495
_logs.Should().HaveCount(3);
9596
_logs.Where(z => z.Type == MessageType.Error).Should().HaveCount(2);
@@ -125,7 +126,7 @@ public async Task Logs_Are_Sent_To_Client_From_Server_Respecting_TraceLevel()
125126
logger.LogTrace("Just gotta let you trace!");
126127
logger.LogDebug("Just gotta let you debug!");
127128

128-
await Task.Delay(1001);
129+
await _logs.DelayUntilCount(4, CancellationToken);
129130

130131
_logs.Should().HaveCount(4);
131132
_logs.Where(z => z.Type == MessageType.Error).Should().HaveCount(2);

test/Lsp.Tests/Integration/LogMessageTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1010
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
1111
using OmniSharp.Extensions.LanguageServer.Server;
12+
using TestingUtils;
1213
using Xunit;
1314
using Xunit.Abstractions;
1415

@@ -42,7 +43,7 @@ public async Task Should_Log_Messages_Through_Window_Extension_Methods()
4243
}
4344
);
4445

45-
await Task.Delay(1000);
46+
await _receivedMessages.DelayUntilCount(6, CancellationToken);
4647

4748
_receivedMessages.Should().HaveCount(6);
4849
_receivedMessages.Should().Contain(z => z.Type == MessageType.Error);
@@ -71,7 +72,7 @@ public async Task Should_Log_Messages_Through_Server_Extension_Methods()
7172
}
7273
);
7374

74-
await Task.Delay(1000);
75+
await _receivedMessages.DelayUntilCount(6, CancellationToken);
7576

7677
_receivedMessages.Should().HaveCount(6);
7778
_receivedMessages.Should().Contain(z => z.Type == MessageType.Error);

test/Lsp.Tests/Integration/PartialItemsTests.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using OmniSharp.Extensions.LanguageServer.Protocol.Progress;
1515
using OmniSharp.Extensions.LanguageServer.Protocol.Server.WorkDone;
1616
using OmniSharp.Extensions.LanguageServer.Server;
17+
using TestingUtils;
1718
using Xunit;
1819
using Xunit.Abstractions;
1920

@@ -123,7 +124,8 @@ public async Task Should_Behave_Like_An_Observable_With_WorkDone()
123124
Observer.Create<WorkDoneProgress>(z => work.Add(z))
124125
).Subscribe(x => items.AddRange(x));
125126

126-
await Task.Delay(1000);
127+
128+
await work.DelayUntilCount(6, CancellationToken);
127129
await SettleNext();
128130

129131
var workResults = work.Select(z => z.Message);

test/Lsp.Tests/Integration/ProgressTests.cs

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Reactive;
5+
using System.Reactive.Disposables;
46
using System.Reactive.Linq;
57
using System.Reactive.Threading.Tasks;
68
using System.Threading.Tasks;
@@ -14,6 +16,7 @@
1416
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1517
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
1618
using OmniSharp.Extensions.LanguageServer.Server;
19+
using TestingUtils;
1720
using Xunit;
1821
using Xunit.Abstractions;
1922

@@ -66,13 +69,16 @@ public async Task Should_Send_Progress_From_Server_To_Client()
6669
}
6770
);
6871

69-
await Task.Delay(1000);
70-
71-
workDoneObservable.Dispose();
72+
await Observable.Create<Unit>(
73+
observer => new CompositeDisposable() {
74+
observable.Select(z => z.Value).Take(5).Subscribe(_ => observer.OnNext(Unit.Default), observer.OnCompleted),
75+
workDoneObservable
76+
}
77+
).ToTask(CancellationToken);
7278

7379
var data = await observable.Select(z => z.Value).ToArray().ToTask(CancellationToken);
7480

75-
data.Should().ContainInOrder(new [] {"1", "3", "2", "4", "5" });
81+
data.Should().ContainInOrder(new[] { "1", "3", "2", "4", "5" });
7682
}
7783

7884
[Fact]
@@ -111,13 +117,16 @@ public async Task Should_Send_Progress_From_Client_To_Server()
111117
}
112118
);
113119

114-
await Task.Delay(1000);
115-
116-
workDoneObservable.Dispose();
120+
await Observable.Create<Unit>(
121+
observer => new CompositeDisposable() {
122+
observable.Select(z => z.Value).Take(5).Subscribe(_ => observer.OnNext(Unit.Default), observer.OnCompleted),
123+
workDoneObservable
124+
}
125+
).ToTask(CancellationToken);
117126

118127
var data = await observable.Select(z => z.Value).ToArray().ToTask(CancellationToken);
119128

120-
data.Should().ContainInOrder(new [] {"1", "3", "2", "4", "5" });
129+
data.Should().ContainInOrder(new[] { "1", "3", "2", "4", "5" });
121130
}
122131

123132
[Fact]

test/Lsp.Tests/Integration/RequestCancellationTests.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
1616
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1717
using OmniSharp.Extensions.LanguageServer.Server;
18+
using TestingUtils;
1819
using Xunit;
1920
using Xunit.Abstractions;
2021

@@ -132,7 +133,7 @@ public async Task Can_Publish_Diagnostics_Delayed()
132133

133134
await SettleNext();
134135

135-
await Task.Delay(1000);
136+
await _diagnostics.DelayUntilCount(1, CancellationToken);
136137

137138
_diagnostics.Should().HaveCount(1);
138139
}

test/Lsp.Tests/Integration/ShowMessageTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
1111
using OmniSharp.Extensions.LanguageServer.Protocol.Window;
1212
using OmniSharp.Extensions.LanguageServer.Server;
13+
using TestingUtils;
1314
using Xunit;
1415
using Xunit.Abstractions;
1516

@@ -43,7 +44,7 @@ public async Task Should_Show_Messages_Through_Window_Extension_Methods()
4344
}
4445
);
4546

46-
await Task.Delay(1000);
47+
await _receivedMessages.DelayUntilCount(6, CancellationToken);
4748

4849
_receivedMessages.Should().HaveCount(6);
4950
_receivedMessages.Should().Contain(z => z.Type == MessageType.Error);
@@ -72,7 +73,7 @@ public async Task Should_Show_Messages_Through_Server_Extension_Methods()
7273
}
7374
);
7475

75-
await Task.Delay(1000);
76+
await _receivedMessages.DelayUntilCount(6, CancellationToken);
7677

7778
_receivedMessages.Should().HaveCount(6);
7879
_receivedMessages.Should().Contain(z => z.Type == MessageType.Error);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Xunit;
8+
9+
namespace TestingUtils
10+
{
11+
public class FactWithSkipOnAttribute : FactAttribute
12+
{
13+
private readonly SkipOnPlatform[] _platformsToSkip;
14+
private string _skip;
15+
16+
public FactWithSkipOnAttribute(params SkipOnPlatform[] platformsToSkip)
17+
{
18+
_platformsToSkip = platformsToSkip;
19+
}
20+
21+
public override string Skip
22+
{
23+
get => !UnitTestDetector.IsCI() && _platformsToSkip.Any(UnitTestDetector.PlatformToSkipPredicate)
24+
? "Skipped on platform" + ( string.IsNullOrWhiteSpace(_skip) ? "" : " because " + _skip )
25+
: null;
26+
set => _skip = value;
27+
}
28+
}
29+
30+
public static class TestHelper
31+
{
32+
public static async Task DelayUntil<T>(Func<T> valueFunc, Func<T, bool> func, CancellationToken cancellationToken, TimeSpan? delay = null)
33+
{
34+
while (true)
35+
{
36+
if (func(valueFunc())) return;
37+
await Task.Delay(delay ?? TimeSpan.FromMilliseconds(100), cancellationToken);
38+
}
39+
}
40+
41+
public static async Task DelayUntil(Func<bool> func, CancellationToken cancellationToken, TimeSpan? delay = null)
42+
{
43+
while (true)
44+
{
45+
if (func()) return;
46+
await Task.Delay(delay ?? TimeSpan.FromMilliseconds(100), cancellationToken);
47+
}
48+
}
49+
50+
public static Task DelayUntil<T>(this T value, Func<T, bool> func, CancellationToken cancellationToken, TimeSpan? delay = null)
51+
{
52+
return DelayUntil(() => value, func, cancellationToken, delay);
53+
}
54+
55+
public static Task DelayUntilCount<T>(this T value, int count, CancellationToken cancellationToken, TimeSpan? delay = null) where T : IEnumerable
56+
{
57+
return DelayUntil(() => value.OfType<object>().Count() >= count, cancellationToken, delay);
58+
}
59+
}
60+
}

test/TestingUtils/SkipOnPlatform.cs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace TestingUtils
2+
{
3+
public enum SkipOnPlatform
4+
{
5+
Linux,
6+
Mac,
7+
Windows,
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System.Linq;
2+
using Xunit;
3+
4+
namespace TestingUtils
5+
{
6+
public class TheoryWithSkipOnAttribute : TheoryAttribute
7+
{
8+
private readonly SkipOnPlatform[] _platformsToSkip;
9+
private string _skip;
10+
11+
public TheoryWithSkipOnAttribute(params SkipOnPlatform[] platformsToSkip)
12+
{
13+
_platformsToSkip = platformsToSkip;
14+
}
15+
16+
public override string Skip
17+
{
18+
get => !UnitTestDetector.IsCI() && _platformsToSkip.Any(UnitTestDetector.PlatformToSkipPredicate)
19+
? "Skipped on platform" + ( string.IsNullOrWhiteSpace(_skip) ? "" : " because " + _skip )
20+
: null;
21+
set => _skip = value;
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)