package org.hamcrest.core;

import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.AbstractMatcherTest.assertMismatchDescription;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.CombinableMatcher.both;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertEquals;

public class CombinableTest {
  private static final CombinableMatcher<Integer> EITHER_3_OR_4 = CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4));
  private static final CombinableMatcher<Integer> NOT_3_AND_NOT_4 = CombinableMatcher.<Integer>both(not(equalTo(3))).and(not(equalTo(4)));

  @Test
  public void bothAcceptsAndRejects() {
    assertThat(2, NOT_3_AND_NOT_4);
    assertThat(3, not(NOT_3_AND_NOT_4));
  }

  @Test
  public void acceptsAndRejectsThreeAnds() {
    CombinableMatcher<? super Integer> tripleAnd = NOT_3_AND_NOT_4.and(equalTo(2));
    assertThat(2, tripleAnd);
    assertThat(3, not(tripleAnd));
  }

  @Test
  public void bothDescribesItself() {
    assertEquals("(not <3> and not <4>)", NOT_3_AND_NOT_4.toString());
    assertMismatchDescription("not <3> was <3>", NOT_3_AND_NOT_4, 3);
  }

  @Test
  public void eitherAcceptsAndRejects() {
    assertThat(3, EITHER_3_OR_4);
    assertThat(6, not(EITHER_3_OR_4));
  }

  @Test
  public void acceptsAndRejectsThreeOrs() {
    final CombinableMatcher<Integer> orTriple = EITHER_3_OR_4.or(equalTo(11));
    assertThat(11, orTriple);
    assertThat(9, not(orTriple));
  }

  @Test
  public void eitherDescribesItself() {
    Assert.assertEquals("(<3> or <4>)", EITHER_3_OR_4.toString());
    assertMismatchDescription("was <6>", EITHER_3_OR_4, 6);
  }

  @Test
  public void picksUpTypeFromLeftHandSideOfExpression() {
    assertThat("yellow", both(equalTo("yellow")).and(notNullValue()));
  }
}

package org.hamcrest.core;

import static org.hamcrest.AbstractMatcherTest.assertDescription;
import static org.hamcrest.AbstractMatcherTest.assertDoesNotMatch;
import static org.hamcrest.AbstractMatcherTest.assertMatches;
import static org.hamcrest.AbstractMatcherTest.assertMismatchDescription;
import static org.hamcrest.AbstractMatcherTest.assertNullSafe;
import static org.hamcrest.AbstractMatcherTest.assertUnknownTypeSafe;
import static org.hamcrest.core.CombinableMatcher.both;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;

import org.hamcrest.Matcher;
import org.junit.Test;

public final class CombinableTest {
    private static final CombinableMatcher<Integer> EITHER_3_OR_4 = CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4));
    private static final CombinableMatcher<Integer> NOT_3_AND_NOT_4 = CombinableMatcher.<Integer>both(not(equalTo(3))).and(not(equalTo(4)));

    @Test public void
    copesWithNullsAndUnknownTypes() {
        assertNullSafe(EITHER_3_OR_4);
        assertNullSafe(NOT_3_AND_NOT_4);
        assertUnknownTypeSafe(EITHER_3_OR_4);
        assertUnknownTypeSafe(NOT_3_AND_NOT_4);
    }

    @Test public void
    bothAcceptsAndRejects() {
        assertMatches("both didn't pass", NOT_3_AND_NOT_4, 2);
        assertDoesNotMatch("both didn't fail", NOT_3_AND_NOT_4, 3);
    }

    @Test public void
    acceptsAndRejectsThreeAnds() {
        CombinableMatcher<? super Integer> tripleAnd = NOT_3_AND_NOT_4.and(equalTo(2));
        
        assertMatches("tripleAnd didn't pass", tripleAnd, 2);
        assertDoesNotMatch("tripleAnd didn't fail", tripleAnd, 3);
    }

    @Test public void
    bothDescribesItself() {
        assertDescription("(not <3> and not <4>)", NOT_3_AND_NOT_4);
        assertMismatchDescription("not <3> was <3>", NOT_3_AND_NOT_4, 3);
    }

    @Test public void
    eitherAcceptsAndRejects() {
        assertMatches("either didn't pass", EITHER_3_OR_4, 3);
        assertDoesNotMatch("either didn't fail", EITHER_3_OR_4, 6);
    }

    @Test public void
    acceptsAndRejectsThreeOrs() {
        final CombinableMatcher<Integer> tripleOr = EITHER_3_OR_4.or(equalTo(11));
        
        assertMatches("tripleOr didn't pass", tripleOr, 11);
        assertDoesNotMatch("tripleOr didn't fail", tripleOr, 9);
    }

    @Test public void
    eitherDescribesItself() {
        assertDescription("(<3> or <4>)", EITHER_3_OR_4);
        assertMismatchDescription("was <6>", EITHER_3_OR_4, 6);
    }

    @Test public void
    picksUpTypeFromLeftHandSideOfExpression() {
        @SuppressWarnings("unused")
        Matcher<String> matcher = both(equalTo("yellow")).and(notNullValue());
    }
}

convert to JUnit4 test