// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using Microsoft.Reactive.Testing; using ReactiveTests.Dummies; using Xunit; namespace ReactiveTests.Tests { public class MinByTest : ReactiveTest { [Fact] public void MinBy_ArgumentChecking() { ReactiveAssert.Throws(() => Observable.MinBy(default(IObservable), x => x)); ReactiveAssert.Throws(() => Observable.MinBy(DummyObservable.Instance, default(Func))); ReactiveAssert.Throws(() => Observable.MinBy(default(IObservable), x => x, Comparer.Default)); ReactiveAssert.Throws(() => Observable.MinBy(DummyObservable.Instance, default, Comparer.Default)); ReactiveAssert.Throws(() => Observable.MinBy(DummyObservable.Instance, x => x, null)); } [Fact] public void MinBy_Empty() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( OnNext>>(250, x => x.Count == 0), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Return() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(2, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( OnNext>>(250, x => x.SequenceEqual(new[] { new KeyValuePair(2, "a"), })), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Some() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(3, "b")), OnNext(220, new KeyValuePair(2, "c")), OnNext(230, new KeyValuePair(4, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( OnNext>>(250, x => x.SequenceEqual(new[] { new KeyValuePair(2, "c"), })), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Multiple() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(3, "b")), OnNext(215, new KeyValuePair(2, "d")), OnNext(220, new KeyValuePair(3, "c")), OnNext(225, new KeyValuePair(2, "y")), OnNext(230, new KeyValuePair(4, "a")), OnNext(235, new KeyValuePair(4, "r")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( OnNext>>(250, x => x.SequenceEqual(new[] { new KeyValuePair(2, "d"), new KeyValuePair(2, "y"), })), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Throw() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnError>(210, ex) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( OnError>>(210, ex) ); xs.Subscriptions.AssertEqual( Subscribe(200, 210) ); } [Fact] public void MinBy_Never() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key) ); res.Messages.AssertEqual( ); xs.Subscriptions.AssertEqual( Subscribe(200, 1000) ); } [Fact] public void MinBy_Comparer_Empty() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ReverseComparer(Comparer.Default)) ); res.Messages.AssertEqual( OnNext>>(250, x => x.Count == 0), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Comparer_Return() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(2, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ReverseComparer(Comparer.Default)) ); res.Messages.AssertEqual( OnNext>>(250, x => x.SequenceEqual(new[] { new KeyValuePair(2, "a"), })), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Comparer_Some() { var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(3, "b")), OnNext(220, new KeyValuePair(20, "c")), OnNext(230, new KeyValuePair(4, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ReverseComparer(Comparer.Default)) ); res.Messages.AssertEqual( OnNext>>(250, x => x.SequenceEqual(new[] { new KeyValuePair(20, "c"), })), OnCompleted>>(250) ); xs.Subscriptions.AssertEqual( Subscribe(200, 250) ); } [Fact] public void MinBy_Comparer_Throw() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnError>(210, ex) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ReverseComparer(Comparer.Default)) ); res.Messages.AssertEqual( OnError>>(210, ex) ); xs.Subscriptions.AssertEqual( Subscribe(200, 210) ); } [Fact] public void MinBy_Comparer_Never() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ReverseComparer(Comparer.Default)) ); res.Messages.AssertEqual( ); xs.Subscriptions.AssertEqual( Subscribe(200, 1000) ); } [Fact] public void MinBy_SelectorThrows() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(3, "b")), OnNext(220, new KeyValuePair(2, "c")), OnNext(230, new KeyValuePair(4, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy, int>(x => { throw ex; }) ); res.Messages.AssertEqual( OnError>>(210, ex) ); xs.Subscriptions.AssertEqual( Subscribe(200, 210) ); } [Fact] public void MinBy_ComparerThrows() { var ex = new Exception(); var scheduler = new TestScheduler(); var xs = scheduler.CreateHotObservable( OnNext(150, new KeyValuePair(1, "z")), OnNext(210, new KeyValuePair(3, "b")), OnNext(220, new KeyValuePair(2, "c")), OnNext(230, new KeyValuePair(4, "a")), OnCompleted>(250) ); var res = scheduler.Start(() => xs.MinBy(x => x.Key, new ThrowingComparer(ex)) ); res.Messages.AssertEqual( OnError>>(220, ex) ); xs.Subscriptions.AssertEqual( Subscribe(200, 220) ); } private class ReverseComparer : IComparer { private IComparer _comparer; public ReverseComparer(IComparer comparer) { _comparer = comparer; } public int Compare(T x, T y) { return -_comparer.Compare(x, y); } } private class ThrowingComparer : IComparer { private readonly Exception _ex; public ThrowingComparer(Exception ex) { _ex = ex; } public int Compare(T x, T y) { throw _ex; } } } }