@Test
 public void testEquality() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("new %s()", EqualsTester.class)
               .addLine("    .addEqualityGroup(")
               .addLine("        DataType.builder().build(),")
               .addLine("        DataType.builder().build())")
               .addLine("    .addEqualityGroup(")
               .addLine("        DataType.builder()")
               .addLine("            .putItems(\"one\", \"A\")")
               .addLine("            .putItems(\"two\", \"B\")")
               .addLine("            .build(),")
               .addLine("        DataType.builder()")
               .addLine("            .putItems(\"two\", \"B\")")
               .addLine("            .putItems(\"one\", \"A\")")
               .addLine("            .build())")
               .addLine("    .addEqualityGroup(")
               .addLine("        DataType.builder()")
               .addLine("            .putItems(\"one\", \"A\")")
               .addLine("            .putItems(\"one\", \"B\")")
               .addLine("            .build())")
               .addLine("    .addEqualityGroup(")
               .addLine("        DataType.builder()")
               .addLine("            .putItems(\"one\", \"B\")")
               .addLine("            .putItems(\"one\", \"A\")")
               .addLine("            .build())")
               .addLine("    .testEquals();")
               .build())
       .runTest();
 }
 @Test
 public void testOverridingPut_primitives() {
   behaviorTester
       .with(new Processor())
       .with(
           new SourceBuilder()
               .addLine("package com.example;")
               .addLine("@%s", FreeBuilder.class)
               .addLine("public abstract class DataType {")
               .addLine("  public abstract %s<Integer, Character> getItems();", Multimap.class)
               .addLine("")
               .addLine("  public static class Builder extends DataType_Builder {")
               .addLine("    @Override public Builder putItems(int unused, char unused2) {")
               .addLine("      return this;")
               .addLine("    }")
               .addLine("  }")
               .addLine("  public static Builder builder() {")
               .addLine("    return new Builder();")
               .addLine("  }")
               .addLine("}")
               .build())
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(0, 'A')")
               .addLine("    .putAllItems(1, %s.of('B', 'C'))", ImmutableList.class)
               .addLine("    .putAllItems(%s.of(3, 'D'))", ImmutableMultimap.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems()).isEmpty();")
               .build())
       .runTest();
 }
 private void testPropertyOfMultimapSubclassType(Class<?> propertyType) {
   behaviorTester
       .with(new Processor())
       .with(
           new SourceBuilder()
               .addLine("package com.example;")
               .addLine("@%s", FreeBuilder.class)
               .addLine("public abstract class DataType {")
               .addLine("  public abstract %s<String, String> getItems();", propertyType)
               .addLine("")
               .addLine("  public static class Builder extends DataType_Builder {}")
               .addLine("  public static Builder builder() {")
               .addLine("    return new Builder();")
               .addLine("  }")
               .addLine("}")
               .build())
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .putItems(\"two\", \"B\")")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"one\", \"A\")")
               .addLine("    .and(\"two\", \"B\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testOverridingPut() {
   behaviorTester
       .with(new Processor())
       .with(
           new SourceBuilder()
               .addLine("package com.example;")
               .addLine("@%s", FreeBuilder.class)
               .addLine("public abstract class DataType {")
               .addLine("  public abstract %s<String, String> getItems();", Multimap.class)
               .addLine("")
               .addLine("  public static class Builder extends DataType_Builder {")
               .addLine("    @Override public Builder putItems(String unused, String unused2) {")
               .addLine("      return this;")
               .addLine("    }")
               .addLine("  }")
               .addLine("  public static Builder builder() {")
               .addLine("    return new Builder();")
               .addLine("  }")
               .addLine("}")
               .build())
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(\"zero\", \"A\")")
               .addLine("    .putAllItems(\"one\", %s.of(\"B\", \"C\"))", ImmutableList.class)
               .addLine("    .putAllItems(%s.of(\"three\", \"D\"))", ImmutableMultimap.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems()).isEmpty();")
               .build())
       .runTest();
 }
 @Test
 public void testDefaultEmpty_primitives() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PRIMITIVES)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder().build();")
               .addLine("%s<Integer, Character> foo = value.getItems();", Multimap.class)
               .addLine("assertThat(foo).isEmpty();")
               .build())
       .runTest();
 }
 @Test
 public void testDefaultEmpty() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder().build();")
               .addLine("%s<String, String> foo = value.getItems();", Multimap.class)
               .addLine("assertThat(foo).isEmpty();")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_nullValue() {
   thrown.expect(NullPointerException.class);
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("new DataType.Builder()")
               .addLine("    .putAllItems(\"one\", %s.newArrayList(\"A\", null));", Lists.class)
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_nullKey() {
   thrown.expect(NullPointerException.class);
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("new DataType.Builder()")
               .addLine("    .putAllItems(null, %s.of(\"A\", \"B\"));", ImmutableList.class)
               .build())
       .runTest();
 }
 @Test
 public void testRemoveAll_nullKey() {
   thrown.expect(NullPointerException.class);
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("new DataType.Builder()")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .removeAllItems((String) null);")
               .build())
       .runTest();
 }
 @Test
 public void testGet_returnsUnmodifiableMultimap() {
   thrown.expect(UnsupportedOperationException.class);
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType.Builder builder = new DataType.Builder();")
               .addLine("%s<String, String> itemsView = builder.getItems();", Multimap.class)
               .addLine("itemsView.put(\"anything\", \"anything\");")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllMultimap_nullValue() {
   thrown.expect(NullPointerException.class);
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("%1$s<String, String> values = %1$s.create();", LinkedListMultimap.class)
               .addLine("values.put(\"one\", null);")
               .addLine("new DataType.Builder().putAllItems(values);")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_duplicate() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putAllItems(\"one\", %s.of(\"A\", \"A\"))", ImmutableList.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"one\", \"A\")")
               .addLine("    .and(\"one\", \"A\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testRemoveAll_doesNotThrowIfKeyNotPresent() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putAllItems(%s.of(", ImmutableMultimap.class)
               .addLine("        \"two\", \"Blue\"))")
               .addLine("    .removeAllItems(\"one\")")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"two\", \"Blue\")")
               .addLine("    .andNothingElse();")
               .build())
       .runTest();
 }
 @Test
 public void testPut_primitives() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PRIMITIVES)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(1, 'A')")
               .addLine("    .putItems(2, 'B')")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(1, 'A')")
               .addLine("    .and(2, 'B')")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_iteratesOnce() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine(
                   "    .putAllItems(\"one\", new %s(\"A\", \"B\"))", DodgyStringIterable.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"one\", \"A\")")
               .addLine("    .and(\"one\", \"B\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testGet_returnsLiveView() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType.Builder builder = new DataType.Builder();")
               .addLine("%s<String, String> itemsView = builder.getItems();", ListMultimap.class)
               .addLine("assertThat(itemsView).isEmpty();")
               .addLine("builder.putItems(\"one\", \"A\");")
               .addLine("assertThat(itemsView).contains(\"one\", \"A\").andNothingElse();")
               .addLine("builder.clearItems();")
               .addLine("assertThat(itemsView).isEmpty();")
               .addLine("builder.putItems(\"three\", \"C\");")
               .addLine("assertThat(itemsView).contains(\"three\", \"C\").andNothingElse();")
               .build())
       .runTest();
 }
 @Test
 public void testMergeFrom_builder() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType.Builder template = DataType.builder()")
               .addLine("    .putItems(\"one\", \"A\");")
               .addLine("DataType.Builder builder = DataType.builder()")
               .addLine("    .putItems(\"two\", \"B\")")
               .addLine("    .mergeFrom(template);")
               .addLine("assertThat(builder.build().getItems())")
               .addLine("    .contains(\"two\", \"B\")")
               .addLine("    .and(\"one\", \"A\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_primitiveKey() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PRIMITIVE_KEY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putAllItems(1, %s.of(\"A\", \"B\"))", ImmutableList.class)
               .addLine("    .putAllItems(2, %s.of(\"Blue\"))", ImmutableSet.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(1, \"A\")")
               .addLine("    .and(1, \"B\")")
               .addLine("    .and(2, \"Blue\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testRemoveAll_primitives() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PRIMITIVES)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putAllItems(%s.of(", ImmutableMultimap.class)
               .addLine("        1, \'A\',")
               .addLine("        1, \'B\',")
               .addLine("        2, \'B\'))")
               .addLine("    .removeAllItems(1)")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(2, \'B\')")
               .addLine("    .andNothingElse();")
               .build())
       .runTest();
 }
 @Test
 public void testPutAllIterable_primitiveValue() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PRIMITIVE_VALUE)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putAllItems(\"one\", %s.of('A\', 'B'))", ImmutableList.class)
               .addLine("    .putAllItems(\"two\", %s.of('C'))", ImmutableSet.class)
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"one\", 'A')")
               .addLine("    .and(\"one\", 'B')")
               .addLine("    .and(\"two\", 'C')")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testBuilderClear() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .clear()")
               .addLine("    .putItems(\"two\", \"B\")")
               .addLine("    .putItems(\"one\", \"C\")")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"two\", \"B\")")
               .addLine("    .and(\"one\", \"C\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testPut_duplicate() {
   behaviorTester
       .with(new Processor())
       .with(MULTIMAP_PROPERTY)
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .putItems(\"two\", \"B\")")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .build();")
               .addLine("assertThat(value.getItems())")
               .addLine("    .contains(\"one\", \"A\")")
               .addLine("    .and(\"one\", \"A\")") // ImmutableMultimap keeps keys together
               .addLine("    .and(\"two\", \"B\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }
 @Test
 public void testJacksonInteroperability() {
   // See also https://github.com/google/FreeBuilder/issues/68
   behaviorTester
       .with(new Processor())
       .with(
           new SourceBuilder()
               .addLine("package com.example;")
               .addLine("import " + JsonProperty.class.getName() + ";")
               .addLine("@%s", FreeBuilder.class)
               .addLine("@%s(builder = DataType.Builder.class)", JsonDeserialize.class)
               .addLine("public interface DataType {")
               .addLine(
                   "  @JsonProperty(\"stuff\") %s<String, String> getItems();", Multimap.class)
               .addLine("")
               .addLine("  class Builder extends DataType_Builder {}")
               .addLine("}")
               .build())
       .with(
           testBuilder()
               .addLine("DataType value = new DataType.Builder()")
               .addLine("    .putItems(\"one\", \"A\")")
               .addLine("    .putItems(\"two\", \"B\")")
               .addLine("    .build();")
               .addLine("%1$s mapper = new %1$s()", ObjectMapper.class)
               .addLine("    .registerModule(new %s());", GuavaModule.class)
               .addLine("String json = mapper.writeValueAsString(value);")
               .addLine("DataType clone = mapper.readValue(json, DataType.class);")
               .addLine("assertThat(clone.getItems())")
               .addLine("    .contains(\"one\", \"A\")")
               .addLine("    .and(\"two\", \"B\")")
               .addLine("    .andNothingElse()")
               .addLine("    .inOrder();")
               .build())
       .runTest();
 }