Package fj.demo.test

Source Code of fj.demo.test.EqualsHashCode$MyClass

package fj.demo.test;

import fj.F;
import fj.F2;
import fj.F3;
import static fj.Function.curry;
import fj.test.Arbitrary;
import static fj.test.Arbitrary.arbByte;
import static fj.test.Arbitrary.arbCharacter;
import static fj.test.Arbitrary.arbitrary;
import static fj.test.Bool.bool;
import static fj.test.CheckResult.summary;
import fj.test.Property;
import static fj.test.Property.property;

/*
Given the equals and hashCode implementation of MyClass, then check that if two
instances (m1 and m2) are equal, then the two hash codes are also equal.

m1.equals(m2).implies(m1.hashCode() == m2.hashCode())

Note this requires a custom Arbitrary to generate MyClass instances that are
more likely to be equal, since otherwise, you'd be waiting a long time for the
generator to produce values where this premise holds true. This is achieved by
using a restrictive arbitrary for bytes and Strings (the components of MyClass).
These restrictive arbitrary implementations produces a (very small) subset of
the possible byte and String values to assist in providing a true premise (that
m1 equals m2).
*/
public final class EqualsHashCode {
  public static final class MyClass {
    private final byte b;
    private final String s;

    MyClass(final byte b, final String s) {
      this.b = b;
      this.s = s;
    }

    public byte b() { return b; }
    public String s() { return s; }

    public boolean equals(final Object o) {
      return o != null &&
          o.getClass() == MyClass.class &&
          b == ((MyClass)o).b &&
          s.equals(((MyClass)o).s);
    }

    public int hashCode() {
      final int p = 419;
      int result = 239;
      result = p * result + b;
      result = p * result + s.hashCode();
      return result;
    }
  }

  public static void main(final String[] args) {
    // Restrictive arbitrary for Byte, produces from three possible values.
    final Arbitrary<Byte> arbByteR = arbitrary(arbByte.gen.map(new F<Byte, Byte>() {
      public Byte f(final Byte b) {
        return (byte)(b % 3);
      }
    }));

    // Restrictive arbitrary for String, produces from twelve (2 * 3 * 2) possible values.
    final Arbitrary<String> arbStringR = arbitrary(arbCharacter.gen.bind(arbCharacter.gen, arbCharacter.gen, curry(new F3<Character, Character, Character, String>() {
      public String f(final Character c1, final Character c2, final Character c3) {
        return new String(new char[]{(char)(c1 % 2 + 'a'), (char)(c2 % 3 + 'a'), (char)(c3 % 2 + 'a')});
      }
    })));

    // Arbitrary for MyClass that uses the restrictive arbitraries above.
    // We are using the monad pattern (bind) to make this a trivial exercise.
    final Arbitrary<MyClass> arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry(new F2<Byte, String, MyClass>() {
      public MyClass f(final Byte b, final String s) {
        return new MyClass(b, s);
      }
    })));

    // Finally the property.
    // if m1 equals m2, then this implies that m1's hashCode is equal to m2's hashCode.
    final Property p = property(arbMyClass, arbMyClass, new F2<MyClass, MyClass, Property>() {
      public Property f(final MyClass m1, final MyClass m2) {
        return bool(m1.equals(m2)).implies(m1.hashCode() == m2.hashCode());
      }
    });
    // at least 100 from 10,000 should satisfy the premise (m1.equals(m2)) 
    summary.println(p.check(100, 10000, 0, 100)); // OK, passed 100 tests (4776 discarded).
  }
}
TOP

Related Classes of fj.demo.test.EqualsHashCode$MyClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.