/*
 * Copyright (c) 2011-2016 Pivotal Software Inc, All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package reactor.core.publisher;

import org.junit.Assert;
import org.junit.Test;
import reactor.test.TestSubscriber;

public class MonoElementAtTest {

	@Test(expected = NullPointerException.class)
	public void source1Null() {
		new MonoElementAt<>(null, 1);
	}

	@Test(expected = NullPointerException.class)
	public void source2Null() {
		new MonoElementAt<>(null, 1, () -> 1);
	}

	@Test(expected = NullPointerException.class)
	public void defaultSupplierNull() {
		new MonoElementAt<>(Mono.never(), 1, null);
	}

	@Test(expected = IndexOutOfBoundsException.class)
	public void indexNegative1() {
		new MonoElementAt<>(Mono.never(), -1);
	}

	@Test(expected = IndexOutOfBoundsException.class)
	public void indexNegative2() {
		new MonoElementAt<>(Mono.never(), -1, () -> 1);
	}

	@Test
	public void normal() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.range(1, 10).elementAt(0).subscribe(ts);

		ts.assertValues(1)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void normalBackpressured() {
		TestSubscriber<Integer> ts = TestSubscriber.create(0);

		Flux.range(1, 10).elementAt(0).subscribe(ts);

		ts.assertNoValues()
		  .assertNoError()
		  .assertNotComplete();

		ts.request(1);

		ts.assertValues(1)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void normal2() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.range(1, 10).elementAt(4).subscribe(ts);

		ts.assertValues(5)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void normal5Backpressured() {
		TestSubscriber<Integer> ts = TestSubscriber.create(0);

		Flux.range(1, 10).elementAt(4).subscribe(ts);

		ts.assertNoValues()
		  .assertNoError()
		  .assertNotComplete();

		ts.request(1);

		ts.assertValues(5)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void normal3() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.range(1, 10).elementAt(9).subscribe(ts);

		ts.assertValues(10)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void normal3Backpressured() {
		TestSubscriber<Integer> ts = TestSubscriber.create(0);

		Flux.range(1, 10).elementAt(9).subscribe(ts);

		ts.assertNoValues()
		  .assertNoError()
		  .assertNotComplete();

		ts.request(1);

		ts.assertValues(10)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void empty() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.<Integer>empty().elementAt(0).subscribe(ts);

		ts.assertNoValues()
		  .assertError(IndexOutOfBoundsException.class)
		  .assertNotComplete();
	}

	@Test
	public void emptyDefault() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.<Integer>empty().elementAt(0, () -> 20).subscribe(ts);

		ts.assertValues(20)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void emptyDefaultBackpressured() {
		TestSubscriber<Integer> ts = TestSubscriber.create(0);

		Flux.<Integer>empty().elementAt(0, () -> 20).subscribe(ts);

		ts.assertNoValues()
		  .assertNoError()
		  .assertNotComplete();

		ts.request(1);

		ts.assertValues(20)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void nonEmptyDefault() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.range(1, 10).elementAt(20, () -> 20).subscribe(ts);

		ts.assertValues(20)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void nonEmptyDefaultBackpressured() {
		TestSubscriber<Integer> ts = TestSubscriber.create(0);

		Flux.range(1, 10).elementAt(20, () -> 20).subscribe(ts);

		ts.assertNoValues()
		  .assertNoError()
		  .assertNotComplete();

		ts.request(1);

		ts.assertValues(20)
		  .assertNoError()
		  .assertComplete();
	}

	@Test
	public void defaultReturnsNull() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.<Integer>empty().elementAt(0, () -> null).subscribe(ts);

		ts.assertNoValues()
		  .assertError(NullPointerException.class)
		  .assertNotComplete();
	}

	@Test
	public void defaultThrows() {
		TestSubscriber<Integer> ts = TestSubscriber.create();

		Flux.<Integer>empty().elementAt(0, () -> {
			throw new RuntimeException("forced failure");
		}).subscribe(ts);

		ts.assertNoValues()
		  .assertError(RuntimeException.class)
		  .assertErrorWith( e -> Assert.assertTrue(e.getMessage().contains("forced failure")))
		  .assertNotComplete();
	}
}

@@ -668,33 +668,8 @@
 r;%0A%0A
-import org.junit.Assert;%0A
 impo
@@ -687,16 +687,16 @@
 t.Test;%0A
+
 import r
@@ -974,22 +974,16 @@
 null, 1,
- () -%3E
  1);%0A%09%7D%0A
@@ -1366,22 +1366,16 @@
 r(), -1,
- () -%3E
  1);%0A%09%7D%0A
@@ -3287,38 +3287,32 @@
 y().elementAt(0,
- () -%3E
  20).subscribe(t
@@ -3530,22 +3530,16 @@
 entAt(0,
- () -%3E
  20).sub
@@ -3831,38 +3831,32 @@
 0).elementAt(20,
- () -%3E
  20).subscribe(t
@@ -4074,22 +4074,16 @@
 ntAt(20,
- () -%3E
  20).sub
@@ -4257,659 +4257,6 @@
 %09%7D%0A%0A
-%09@Test%0A%09public void defaultReturnsNull() %7B%0A%09%09TestSubscriber%3CInteger%3E ts = TestSubscriber.create();%0A%0A%09%09Flux.%3CInteger%3Eempty().elementAt(0, () -%3E null).subscribe(ts);%0A%0A%09%09ts.assertNoValues()%0A%09%09  .assertError(NullPointerException.class)%0A%09%09  .assertNotComplete();%0A%09%7D%0A%0A%09@Test%0A%09public void defaultThrows() %7B%0A%09%09TestSubscriber%3CInteger%3E ts = TestSubscriber.create();%0A%0A%09%09Flux.%3CInteger%3Eempty().elementAt(0, () -%3E %7B%0A%09%09%09throw new RuntimeException(%22forced failure%22);%0A%09%09%7D).subscribe(ts);%0A%0A%09%09ts.assertNoValues()%0A%09%09  .assertError(RuntimeException.class)%0A%09%09  .assertErrorWith( e -%3E Assert.assertTrue(e.getMessage().contains(%22forced failure%22)))%0A%09%09  .assertNotComplete();%0A%09%7D%0A
 %7D%0A

fix #185 align default constant fallback to T instead of Supplier<T>