package fr.umlv.funreflect;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import java.awt.Color;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.IntStream;

import org.junit.Test;

@SuppressWarnings("static-method")
public class IntrospectorsTest {
  @Test
  public void testIntrospectGet() {
    Point2D.Double point = new Point2D.Double(3.0, 4.0);
    Map<String, Object> map = Introspectors.introspect(point);
    assertEquals(3.0, map.get("x"));
    assertEquals(4.0, map.get("y"));
  }

  @Test
  public void testIntrospectGet2() throws NoSuchMethodException {
    Method method = IntrospectorsTest.class.getMethod("testIntrospectGet2");
    Map<String, Object> map = Introspectors.introspect(method);
    assertEquals(0, map.get("parameterCount"));
  }
  
  @Test
  public void testIntrospectGet3() {
    Color color = Color.BLACK;
    Map<String, Object> map = Introspectors.introspect(color);
    assertEquals(0, map.get("red"));
    assertEquals(0, map.get("green"));
    assertEquals(0, map.get("blue"));
  }
  
  @Test
  public void testIntrospectGetClass() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    assertEquals(Point2D.Double.class, map.get("class"));
  }
  
  @FunctionalInterface
  interface Fun {
    String getValue();
  }
  
  @Test(expected = IndexOutOfBoundsException.class)
  public void testIntrospectRuntimeExceptionPropagation() {
    Fun fun = () -> { throw new IndexOutOfBoundsException(); };
    Map<String, Object> map = Introspectors.introspect(fun);
    map.get("value");
  }
  
  @Test(expected = AssertionError.class)
  public void testIntrospectErrorPropagation() {
    Fun fun = () -> { throw new AssertionError(); };
    Map<String, Object> map = Introspectors.introspect(fun);
    map.get("value");
  }
  
  static class LessFun {
    public String getValue() throws IOException {
      throw new IOException();
    }
  }
  
  @Test(expected = UndeclaredThrowableException.class)
  public void testIntrospectExceptionPropagation() {
    LessFun lessFun = new LessFun();
    Map<String, Object> map = Introspectors.introspect(lessFun);
    map.get("value");
  }
  
  @Test
  public void testIntrospectDouble() {
    Color color = Color.BLACK;
    Map<String, Object> map1 = Introspectors.introspect(color);
    Map<String, Object> map2 = Introspectors.introspect(color);
    map1.forEach((key, value) -> {
      assertEquals(value, map2.get(key));
    });
  }
  
  public void testIntrospectMutation() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    point.setLocation(12, 21);
    assertEquals(12, map.get("x"));
    assertEquals(21, map.get("y"));
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void testIntrospectMutationRemove() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    map.remove("x");
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void testIntrospectMutationPut() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    map.put("x", 101);
  }
  
  @Test
  public void testIntrospectMutationIterator() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    HashSet<Object> set1 = new HashSet<>();
    map.values().iterator().forEachRemaining(set1::add);
    HashSet<Object> set2 = new HashSet<>();
    map.values().iterator().forEachRemaining(set2::add);
    assertEquals(set1, set2);
  }
  
  @Test(expected = UnsupportedOperationException.class)
  public void testIntrospectMutationIteratorRemove() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    Iterator<Entry<String, Object>> it = map.entrySet().iterator();
    it.next();
    it.remove();
  }
  
  @Test
  public void testIntrospectMutationIteratorEntries() {
    Point2D.Double point = new Point2D.Double();
    Map<String, Object> map = Introspectors.introspect(point);
    HashSet<Object> set1 = new HashSet<>();
    map.entrySet().iterator().forEachRemaining(set1::add);
    HashSet<Object> set2 = new HashSet<>();
    map.entrySet().iterator().forEachRemaining(set2::add);
    assertEquals(set1, set2);
  }
  
  static class Max {
    public String get000() { return "000"; }  public String get100() { return "100"; }  public String get200() { return "200"; }
    public String get001() { return "001"; }  public String get101() { return "101"; }  public String get201() { return "201"; }
    public String get002() { return "002"; }  public String get102() { return "102"; }  public String get202() { return "202"; }
    public String get003() { return "003"; }  public String get103() { return "103"; }  public String get203() { return "203"; }
    public String get004() { return "004"; }  public String get104() { return "104"; }  public String get204() { return "204"; }
    public String get006() { return "006"; }  public String get106() { return "106"; }  public String get206() { return "206"; }
    public String get007() { return "007"; }  public String get107() { return "107"; }  public String get207() { return "207"; }
    public String get008() { return "008"; }  public String get108() { return "108"; }  public String get208() { return "208"; }
    public String get009() { return "009"; }  public String get109() { return "109"; }  public String get209() { return "209"; }
    
    public String getXXX() { return "XXX"; }  public String get1XX() { return "1XX"; }  public String get2XX() { return "2XX"; }
    public String getXX1() { return "XX1"; }  public String get1X1() { return "1X1"; }  public String get2X1() { return "2X1"; }
    public String getXX2() { return "XX2"; }  public String get1X2() { return "1X2"; }  public String get2X2() { return "2X2"; }
    public String getXX3() { return "XX3"; }  public String get1X3() { return "1X3"; }  public String get2X3() { return "2X3"; }
    public String getXX4() { return "XX4"; }  public String get1X4() { return "1X4"; }  public String get2X4() { return "2X4"; }
    public String getXX6() { return "XX6"; }  public String get1X6() { return "1X6"; }  public String get2X6() { return "2X6"; }
    public String getXX7() { return "XX7"; }  public String get1X7() { return "1X7"; }  public String get2X7() { return "2X7"; }
    public String getXX8() { return "XX8"; }  public String get1X8() { return "1X8"; }  public String get2X8() { return "2X8"; }
    public String getXX9() { return "XX9"; }  public String get1X9() { return "1X9"; }  public String get2X9() { return "2X9"; }
    
    public String getYYY() { return "YYY"; }  public String get1YY() { return "1YY"; }  public String get2YY() { return "2YY"; }
    public String getYY1() { return "YY1"; }  public String get1Y1() { return "1Y1"; }  public String get2Y1() { return "2Y1"; }
    public String getYY2() { return "YY2"; }  public String get1Y2() { return "1Y2"; }  public String get2Y2() { return "2Y2"; }
    public String getYY3() { return "YY3"; }  public String get1Y3() { return "1Y3"; }  public String get2Y3() { return "2Y3"; }
    public String getYY4() { return "YY4"; }  public String get1Y4() { return "1Y4"; }  public String get2Y4() { return "2Y4"; }
    public String getYY6() { return "YY6"; }  public String get1Y6() { return "1Y6"; }  public String get2Y6() { return "2Y6"; }
    public String getYY7() { return "YY7"; }  public String get1Y7() { return "1Y7"; }  public String get2Y7() { return "2Y7"; }
    public String getYY8() { return "YY8"; }  public String get1Y8() { return "1Y8"; }  public String get2Y8() { return "2Y8"; }
    public String getYY9() { return "YY9"; }  public String get1Y9() { return "1Y9"; }  public String get2Y9() { return "2Y9"; }
    
    public String getZZZ() { return "ZZZ"; }  public String get1ZZ() { return "1ZZ"; }  public String get2ZZ() { return "2ZZ"; }
    public String getZZ1() { return "ZZ1"; }  public String get1Z1() { return "1Z1"; }  public String get2Z1() { return "2Z1"; }
    public String getZZ2() { return "ZZ2"; }  public String get1Z2() { return "1Z2"; }  public String get2Z2() { return "2Z2"; }
    public String getZZ3() { return "ZZ3"; }  public String get1Z3() { return "1Z3"; }  public String get2Z3() { return "2Z3"; }
    public String getZZ4() { return "ZZ4"; }  public String get1Z4() { return "1Z4"; }  public String get2Z4() { return "2Z4"; }
    public String getZZ6() { return "ZZ6"; }  public String get1Z6() { return "1Z6"; }  public String get2Z6() { return "2Z6"; }
    public String getZZ7() { return "ZZ7"; }  public String get1Z7() { return "1Z7"; }  public String get2Z7() { return "2Z7"; }
    public String getZZ8() { return "ZZ8"; }  public String get1Z8() { return "1Z8"; }  public String get2Z8() { return "2Z8"; }
    public String getZZ9() { return "ZZ9"; }  public String get1Z9() { return "1Z9"; }  public String get2Z9() { return "2Z9"; }
    
    public String getAAA() { return "AAA"; }  public String get1AA() { return "1AA"; }  public String get2AA() { return "2AA"; }
    public String getAA1() { return "AA1"; }  public String get1A1() { return "1A1"; }  public String get2A1() { return "2A1"; }
    public String getAA2() { return "AA2"; }  public String get1A2() { return "1A2"; }  public String get2A2() { return "2A2"; }
    public String getAA3() { return "AA3"; }  public String get1A3() { return "1A3"; }  public String get2A3() { return "2A3"; }
    public String getAA4() { return "AA4"; }  public String get1A4() { return "1A4"; }  public String get2A4() { return "2A4"; }
    public String getAA6() { return "AA6"; }  public String get1A6() { return "1A6"; }  public String get2A6() { return "2A6"; }
    public String getAA7() { return "AA7"; }  public String get1A7() { return "1A7"; }  public String get2A7() { return "2A7"; }
    public String getAA8() { return "AA8"; }  public String get1A8() { return "1A8"; }  public String get2A8() { return "2A8"; }
    public String getAA9() { return "AA9"; }  public String get1A9() { return "1A9"; }  public String get2A9() { return "2A9"; }
    
    public String getBBB() { return "BBB"; }  public String get1BB() { return "1BB"; }  public String get2BB() { return "2BB"; }
    public String getBB1() { return "BB1"; }  public String get1B1() { return "1B1"; }  public String get2B1() { return "2B1"; }
    public String getBB2() { return "BB2"; }  public String get1B2() { return "1B2"; }  public String get2B2() { return "2B2"; }
    public String getBB3() { return "BB3"; }  public String get1B3() { return "1B3"; }  public String get2B3() { return "2B3"; }
    public String getBB4() { return "BB4"; }  public String get1B4() { return "1B4"; }  public String get2B4() { return "2B4"; }
    public String getBB6() { return "BB6"; }  public String get1B6() { return "1B6"; }  public String get2B6() { return "2B6"; }
    public String getBB7() { return "BB7"; }  public String get1B7() { return "1B7"; }  public String get2B7() { return "2B7"; }
    public String getBB8() { return "BB8"; }  public String get1B8() { return "1B8"; }  public String get2B8() { return "2B8"; }
    public String getBB9() { return "BB9"; }  public String get1B9() { return "1B9"; }  public String get2B9() { return "2B9"; }
    
    public String getCCC() { return "CCC"; }  public String get1CC() { return "1CC"; }  public String get2CC() { return "2CC"; }
    public String getCC1() { return "CC1"; }  public String get1C1() { return "1C1"; }  public String get2C1() { return "2C1"; }
    public String getCC2() { return "CC2"; }  public String get1C2() { return "1C2"; }  public String get2C2() { return "2C2"; }
    public String getCC3() { return "CC3"; }  public String get1C3() { return "1C3"; }  public String get2C3() { return "2C3"; }
    public String getCC4() { return "CC4"; }  public String get1C4() { return "1C4"; }  public String get2C4() { return "2C4"; }
    public String getCC6() { return "CC6"; }  public String get1C6() { return "1C6"; }  public String get2C6() { return "2C6"; }
    public String getCC7() { return "CC7"; }  public String get1C7() { return "1C7"; }  public String get2C7() { return "2C7"; }
    public String getCC8() { return "CC8"; }  public String get1C8() { return "1C8"; }  public String get2C8() { return "2C8"; }
    public String getCC9() { return "CC9"; }  public String get1C9() { return "1C9"; }  public String get2C9() { return "2C9"; }
    
    public String getDDD() { return "DDD"; }  public String get1DD() { return "1DD"; }  public String get2DD() { return "2DD"; }
    public String getDD1() { return "DD1"; }  public String get1D1() { return "1D1"; }  public String get2D1() { return "2D1"; }
    public String getDD2() { return "DD2"; }  public String get1D2() { return "1D2"; }  public String get2D2() { return "2D2"; }
    public String getDD3() { return "DD3"; }  public String get1D3() { return "1D3"; }  public String get2D3() { return "2D3"; }
    public String getDD4() { return "DD4"; }  public String get1D4() { return "1D4"; }  public String get2D4() { return "2D4"; }
    public String getDD6() { return "DD6"; }  public String get1D6() { return "1D6"; }  public String get2D6() { return "2D6"; }
    public String getDD7() { return "DD7"; }  public String get1D7() { return "1D7"; }  public String get2D7() { return "2D7"; }
    public String getDD8() { return "DD8"; }  public String get1D8() { return "1D8"; }  public String get2D8() { return "2D8"; }
    public String getDD9() { return "DD9"; }  public String get1D9() { return "1D9"; }  public String get2D9() { return "2D9"; }
    
    public String getEEE() { return "EEE"; }  public String get1EE() { return "1EE"; }  public String get2EE() { return "2EE"; }
    public String getEE1() { return "EE1"; }  public String get1E1() { return "1E1"; }  public String get2E1() { return "2E1"; }
    public String getEE2() { return "EE2"; }  public String get1E2() { return "1E2"; }  public String get2E2() { return "2E2"; }
    public String getEE3() { return "EE3"; }  public String get1E3() { return "1E3"; }  public String get2E3() { return "2E3"; }
    public String getEE4() { return "EE4"; }  public String get1E4() { return "1E4"; }  public String get2E4() { return "2E4"; }
    public String getEE6() { return "EE6"; }  public String get1E6() { return "1E6"; }  public String get2E6() { return "2E6"; }
    public String getEE7() { return "EE7"; }  public String get1E7() { return "1E7"; }  public String get2E7() { return "2E7"; }
    public String getEE8() { return "EE8"; }  public String get1E8() { return "1E8"; }  public String get2E8() { return "2E8"; }
    public String getEE9() { return "EE9"; }  public String get1E9() { return "1E9"; }  public String get2E9() { return "2E9"; }
    
    public String getFFF() { return "FFF"; }  public String get1FF() { return "1FF"; }  public String get2FF() { return "2FF"; }
    public String getFF1() { return "FF1"; }  public String get1F1() { return "1F1"; }  public String get2F1() { return "2F1"; }
    public String getFF2() { return "FF2"; }  public String get1F2() { return "1F2"; }  public String get2F2() { return "2F2"; }
    public String getFF3() { return "FF3"; }  public String get1F3() { return "1F3"; }  public String get2F3() { return "2F3"; }
    public String getFF4() { return "FF4"; }  public String get1F4() { return "1F4"; }  public String get2F4() { return "2F4"; }
    public String getFF6() { return "FF6"; }  public String get1F6() { return "1F6"; }  public String get2F6() { return "2F6"; }
    public String getFF7() { return "FF7"; }  public String get1F7() { return "1F7"; }  public String get2F7() { return "2F7"; }
    public String getFF8() { return "FF8"; }  public String get1F8() { return "1F8"; }  public String get2F8() { return "2F8"; }
    public String getFF9() { return "FF9"; }  public String get1F9() { return "1F9"; }  public String get2F9() { return "2F9"; }
    
    public String getGGG() { return "GGG"; }  public String get1GG() { return "1GG"; }  public String get2GG() { return "2GG"; }
    public String getGG1() { return "GG1"; }  public String get1G1() { return "1G1"; }  public String get2G1() { return "2G1"; }
    public String getGG2() { return "GG2"; }  public String get1G2() { return "1G2"; }  public String get2G2() { return "2G2"; }
    public String getGG3() { return "GG3"; }  public String get1G3() { return "1G3"; }  public String get2G3() { return "2G3"; }
    public String getGG4() { return "GG4"; }  public String get1G4() { return "1G4"; }  public String get2G4() { return "2G4"; }
    public String getGG6() { return "GG6"; }  public String get1G6() { return "1G6"; }  public String get2G6() { return "2G6"; }
    public String getGG7() { return "GG7"; }  public String get1G7() { return "1G7"; }  public String get2G7() { return "2G7"; }
    public String getGG8() { return "GG8"; }  public String get1G8() { return "1G8"; }  public String get2G8() { return "2G8"; }
    public String getGG9() { return "GG9"; }  public String get1G9() { return "1G9"; }  public String get2G9() { return "2G9"; }
    
    public String getHHH() { return "HHH"; }  public String get1HH() { return "1HH"; }  public String get2HH() { return "2HH"; }
    public String getHH1() { return "HH1"; }  public String get1H1() { return "1H1"; }  public String get2H1() { return "2H1"; }
    public String getHH2() { return "HH2"; }  public String get1H2() { return "1H2"; }  public String get2H2() { return "2H2"; }
    public String getHH3() { return "HH3"; }  public String get1H3() { return "1H3"; }  public String get2H3() { return "2H3"; }
    public String getHH4() { return "HH4"; }  public String get1H4() { return "1H4"; }  public String get2H4() { return "2H4"; }
    public String getHH6() { return "HH6"; }  public String get1H6() { return "1H6"; }  public String get2H6() { return "2H6"; }
    public String getHH7() { return "HH7"; }  public String get1H7() { return "1H7"; }  public String get2H7() { return "2H7"; }
    public String getHH8() { return "HH8"; }  public String get1H8() { return "1H8"; }  public String get2H8() { return "2H8"; }
    public String getHH9() { return "HH9"; }  public String get1H9() { return "1H9"; }  public String get2H9() { return "2H9"; }
    
    public String getIII() { return "III"; }  public String get1II() { return "1II"; }  public String get2II() { return "2II"; }
    public String getII1() { return "II1"; }  public String get1I1() { return "1I1"; }  public String get2I1() { return "2I1"; }
    public String getII2() { return "II2"; }  public String get1I2() { return "1I2"; }  public String get2I2() { return "2I2"; }
    public String getII3() { return "II3"; }  public String get1I3() { return "1I3"; }  public String get2I3() { return "2I3"; }
    public String getII4() { return "II4"; }  public String get1I4() { return "1I4"; }  public String get2I4() { return "2I4"; }
    public String getII6() { return "II6"; }  public String get1I6() { return "1I6"; }  public String get2I6() { return "2I6"; }
    public String getII7() { return "II7"; }  public String get1I7() { return "1I7"; }  public String get2I7() { return "2I7"; }
    public String getII8() { return "II8"; }  public String get1I8() { return "1I8"; }  public String get2I8() { return "2I8"; }
    public String getII9() { return "II9"; }  public String get1I9() { return "1I9"; }  public String get2I9() { return "2I9"; }
    
    public String getJJJ() { return "JJJ"; }  public String get1JJ() { return "1JJ"; }  public String get2JJ() { return "2JJ"; }
    public String getJJ1() { return "JJ1"; }  public String get1J1() { return "1J1"; }  public String get2J1() { return "2J1"; }
    public String getJJ2() { return "JJ2"; }  public String get1J2() { return "1J2"; }  public String get2J2() { return "2J2"; }
    public String getJJ3() { return "JJ3"; }  public String get1J3() { return "1J3"; }  public String get2J3() { return "2J3"; }
    public String getJJ4() { return "JJ4"; }  public String get1J4() { return "1J4"; }  public String get2J4() { return "2J4"; }
    public String getJJ6() { return "JJ6"; }  public String get1J6() { return "1J6"; }  public String get2J6() { return "2J6"; }
    public String getJJ7() { return "JJ7"; }  public String get1J7() { return "1J7"; }  public String get2J7() { return "2J7"; }
    public String getJJ8() { return "JJ8"; }  public String get1J8() { return "1J8"; }  public String get2J8() { return "2J8"; }
    public String getJJ9() { return "JJ9"; }  public String get1J9() { return "1J9"; }  public String get2J9() { return "2J9"; }
    
    public String getKKK() { return "KKK"; }  public String get1KK() { return "1KK"; }  public String get2KK() { return "2KK"; }
    public String getKK1() { return "KK1"; }  public String get1K1() { return "1K1"; }  public String get2K1() { return "2K1"; }
    public String getKK2() { return "KK2"; }  public String get1K2() { return "1K2"; }  public String get2K2() { return "2K2"; }
    public String getKK3() { return "KK3"; }  public String get1K3() { return "1K3"; }  public String get2K3() { return "2K3"; }
    public String getKK4() { return "KK4"; }  public String get1K4() { return "1K4"; }  public String get2K4() { return "2K4"; }
    public String getKK6() { return "KK6"; }  public String get1K6() { return "1K6"; }  public String get2K6() { return "2K6"; }
    public String getKK7() { return "KK7"; }  public String get1K7() { return "1K7"; }  public String get2K7() { return "2K7"; }
    public String getKK8() { return "KK8"; }  public String get1K8() { return "1K8"; }  public String get2K8() { return "2K8"; }
    public String getKK9() { return "KK9"; }  public String get1K9() { return "1K9"; }  public String get2K9() { return "2K9"; }
    
    public String getLLL() { return "LLL"; }  public String get1LL() { return "1LL"; }  public String get2LL() { return "2LL"; }
    public String getLL1() { return "LL1"; }  public String get1L1() { return "1L1"; }  public String get2L1() { return "2L1"; }
    public String getLL2() { return "LL2"; }  public String get1L2() { return "1L2"; }  public String get2L2() { return "2L2"; }
    public String getLL3() { return "LL3"; }  public String get1L3() { return "1L3"; }  public String get2L3() { return "2L3"; }
    public String getLL4() { return "LL4"; }  public String get1L4() { return "1L4"; }  public String get2L4() { return "2L4"; }
    public String getLL6() { return "LL6"; }  public String get1L6() { return "1L6"; }  public String get2L6() { return "2L6"; }
    public String getLL7() { return "LL7"; }  public String get1L7() { return "1L7"; }  public String get2L7() { return "2L7"; }
    public String getLL8() { return "LL8"; }  public String get1L8() { return "1L8"; }  public String get2L8() { return "2L8"; }
    public String getLL9() { return "LL9"; }  public String get1L9() { return "1L9"; }  public String get2L9() { return "2L9"; }
    
    public String getMMM() { return "MMM"; }  public String get1MM() { return "1MM"; }  public String get2MM() { return "2MM"; }
    public String getMM1() { return "MM1"; }  public String get1M1() { return "1M1"; }  public String get2M1() { return "2M1"; }
    public String getMM2() { return "MM2"; }  public String get1M2() { return "1M2"; }  public String get2M2() { return "2M2"; }
    public String getMM3() { return "MM3"; }  public String get1M3() { return "1M3"; }  public String get2M3() { return "2M3"; }
    public String getMM4() { return "MM4"; }  public String get1M4() { return "1M4"; }  public String get2M4() { return "2M4"; }
    public String getMM6() { return "MM6"; }  public String get1M6() { return "1M6"; }  public String get2M6() { return "2M6"; }
    public String getMM7() { return "MM7"; }  public String get1M7() { return "1M7"; }  public String get2M7() { return "2M7"; }
    public String getMM8() { return "MM8"; }  public String get1M8() { return "1M8"; }  public String get2M8() { return "2M8"; }
    public String getMM9() { return "MM9"; }  public String get1M9() { return "1M9"; }  public String get2M9() { return "2M9"; }
    
    public String getNNN() { return "NNN"; }  public String get1NN() { return "1NN"; }  public String get2NN() { return "2NN"; }
    public String getNN1() { return "NN1"; }  public String get1N1() { return "1N1"; }  public String get2N1() { return "2N1"; }
    public String getNN2() { return "NN2"; }  public String get1N2() { return "1N2"; }  public String get2N2() { return "2N2"; }
    public String getNN3() { return "NN3"; }  public String get1N3() { return "1N3"; }  public String get2N3() { return "2N3"; }
    public String getNN4() { return "NN4"; }  public String get1N4() { return "1N4"; }  public String get2N4() { return "2N4"; }
    public String getNN6() { return "NN6"; }  public String get1N6() { return "1N6"; }  public String get2N6() { return "2N6"; }
    public String getNN7() { return "NN7"; }  public String get1N7() { return "1N7"; }  public String get2N7() { return "2N7"; }
    public String getNN8() { return "NN8"; }  public String get1N8() { return "1N8"; }  public String get2N8() { return "2N8"; }
    public String getNN9() { return "NN9"; }  public String get1N9() { return "1N9"; }  public String get2N9() { return "2N9"; }
    
    public String getOOO() { return "OOO"; }  public String get1OO() { return "1OO"; }  public String get2OO() { return "2OO"; }
    public String getOO1() { return "OO1"; }  public String get1O1() { return "1O1"; }  public String get2O1() { return "2O1"; }
    public String getOO2() { return "OO2"; }  public String get1O2() { return "1O2"; }  public String get2O2() { return "2O2"; }
    public String getOO3() { return "OO3"; }  public String get1O3() { return "1O3"; }  public String get2O3() { return "2O3"; }
    public String getOO4() { return "OO4"; }  public String get1O4() { return "1O4"; }  public String get2O4() { return "2O4"; }
    public String getOO6() { return "OO6"; }  public String get1O6() { return "1O6"; }  public String get2O6() { return "2O6"; }
    public String getOO7() { return "OO7"; }  public String get1O7() { return "1O7"; }  public String get2O7() { return "2O7"; }
    public String getOO8() { return "OO8"; }  public String get1O8() { return "1O8"; }  public String get2O8() { return "2O8"; }
    public String getOO9() { return "OO9"; }  public String get1O9() { return "1O9"; }  public String get2O9() { return "2O9"; }
    
    public String getPPP() { return "PPP"; }  public String get1PP() { return "1PP"; }  public String get2PP() { return "2PP"; }
    public String getPP1() { return "PP1"; }  public String get1P1() { return "1P1"; }  public String get2P1() { return "2P1"; }
    public String getPP2() { return "PP2"; }  public String get1P2() { return "1P2"; }  public String get2P2() { return "2P2"; }
    public String getPP3() { return "PP3"; }  public String get1P3() { return "1P3"; }  public String get2P3() { return "2P3"; }
    public String getPP4() { return "PP4"; }  public String get1P4() { return "1P4"; }  public String get2P4() { return "2P4"; }
    public String getPP6() { return "PP6"; }  public String get1P6() { return "1P6"; }  public String get2P6() { return "2P6"; }
    public String getPP7() { return "PP7"; }  public String get1P7() { return "1P7"; }  public String get2P7() { return "2P7"; }
    public String getPP8() { return "PP8"; }  public String get1P8() { return "1P8"; }  public String get2P8() { return "2P8"; }
    public String getPP9() { return "PP9"; }  public String get1P9() { return "1P9"; }  public String get2P9() { return "2P9"; }
  }
  
  @Test(timeout = 500)
  public void testSlooooow() {
    Max max = new Max();
    Map<String, Object> map = Introspectors.introspect(max);
    map.forEach((key, value) -> {
      if (!key.equals("class")) {
        assertEquals(key.toUpperCase(), map.get(key));
      }
      assertEquals(value, map.get(key));
      
      IntStream.range(0, 3).forEach(i -> {
        IntStream.range('A', 'P').forEach(j -> {
          assertNull(map.get("" + i + ('A' + j) + '5'));
        });
      });
    });
  }
}
