001/*
002 * Copyright (C) 2012 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing.google;
018
019import static com.google.common.collect.testing.Helpers.assertEqualIgnoringOrder;
020
021import com.google.common.annotations.GwtCompatible;
022import com.google.common.collect.Multimap;
023import com.google.common.collect.testing.AbstractContainerTester;
024import com.google.common.collect.testing.Helpers;
025import com.google.common.collect.testing.SampleElements;
026import com.google.errorprone.annotations.CanIgnoreReturnValue;
027import java.util.Arrays;
028import java.util.Collection;
029import java.util.Iterator;
030import java.util.Map.Entry;
031import org.junit.Ignore;
032
033/**
034 * Superclass for all {@code Multimap} testers.
035 *
036 * @author Louis Wasserman
037 */
038@GwtCompatible
039@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
040public abstract class AbstractMultimapTester<K, V, M extends Multimap<K, V>>
041    extends AbstractContainerTester<M, Entry<K, V>> {
042
043  private M multimap;
044
045  protected M multimap() {
046    return multimap;
047  }
048
049  /** @return an array of the proper size with {@code null} as the key of the middle element. */
050  protected Entry<K, V>[] createArrayWithNullKey() {
051    Entry<K, V>[] array = createSamplesArray();
052    int nullKeyLocation = getNullLocation();
053    Entry<K, V> oldEntry = array[nullKeyLocation];
054    array[nullKeyLocation] = Helpers.mapEntry(null, oldEntry.getValue());
055    return array;
056  }
057
058  /** @return an array of the proper size with {@code null} as the value of the middle element. */
059  protected Entry<K, V>[] createArrayWithNullValue() {
060    Entry<K, V>[] array = createSamplesArray();
061    int nullValueLocation = getNullLocation();
062    Entry<K, V> oldEntry = array[nullValueLocation];
063    array[nullValueLocation] = Helpers.mapEntry(oldEntry.getKey(), null);
064    return array;
065  }
066
067  /**
068   * @return an array of the proper size with {@code null} as the key and value of the middle
069   *     element.
070   */
071  protected Entry<K, V>[] createArrayWithNullKeyAndValue() {
072    Entry<K, V>[] array = createSamplesArray();
073    int nullValueLocation = getNullLocation();
074    array[nullValueLocation] = Helpers.mapEntry(null, null);
075    return array;
076  }
077
078  protected V getValueForNullKey() {
079    return getEntryNullReplaces().getValue();
080  }
081
082  protected K getKeyForNullValue() {
083    return getEntryNullReplaces().getKey();
084  }
085
086  private Entry<K, V> getEntryNullReplaces() {
087    Iterator<Entry<K, V>> entries = getSampleElements().iterator();
088    for (int i = 0; i < getNullLocation(); i++) {
089      entries.next();
090    }
091    return entries.next();
092  }
093
094  protected void initMultimapWithNullKey() {
095    resetContainer(getSubjectGenerator().create((Object[]) createArrayWithNullKey()));
096  }
097
098  protected void initMultimapWithNullValue() {
099    resetContainer(getSubjectGenerator().create((Object[]) createArrayWithNullValue()));
100  }
101
102  protected void initMultimapWithNullKeyAndValue() {
103    resetContainer(getSubjectGenerator().create((Object[]) createArrayWithNullKeyAndValue()));
104  }
105
106  protected SampleElements<K> sampleKeys() {
107    return ((TestMultimapGenerator<K, V, ? extends Multimap<K, V>>)
108            getSubjectGenerator().getInnerGenerator())
109        .sampleKeys();
110  }
111
112  protected SampleElements<V> sampleValues() {
113    return ((TestMultimapGenerator<K, V, ? extends Multimap<K, V>>)
114            getSubjectGenerator().getInnerGenerator())
115        .sampleValues();
116  }
117
118  @Override
119  protected Collection<Entry<K, V>> actualContents() {
120    return multimap.entries();
121  }
122
123  // TODO: dispose of this once collection is encapsulated.
124  @Override
125  @CanIgnoreReturnValue
126  protected M resetContainer(M newContents) {
127    multimap = super.resetContainer(newContents);
128    return multimap;
129  }
130
131  @CanIgnoreReturnValue
132  protected Multimap<K, V> resetContainer(Entry<K, V>... newContents) {
133    multimap = super.resetContainer(getSubjectGenerator().create((Object[]) newContents));
134    return multimap;
135  }
136
137  /** @see AbstractContainerTester#resetContainer() */
138  protected void resetCollection() {
139    resetContainer();
140  }
141
142  protected void assertGet(K key, V... values) {
143    assertGet(key, Arrays.asList(values));
144  }
145
146  protected void assertGet(K key, Collection<V> values) {
147    assertEqualIgnoringOrder(values, multimap().get(key));
148
149    if (!values.isEmpty()) {
150      assertEqualIgnoringOrder(values, multimap().asMap().get(key));
151      assertFalse(multimap().isEmpty());
152    } else {
153      assertNull(multimap().asMap().get(key));
154    }
155
156    assertEquals(values.size(), multimap().get(key).size());
157
158    assertEquals(values.size() > 0, multimap().containsKey(key));
159    assertEquals(values.size() > 0, multimap().keySet().contains(key));
160    assertEquals(values.size() > 0, multimap().keys().contains(key));
161  }
162
163  protected final K k0() {
164    return e0().getKey();
165  }
166
167  protected final V v0() {
168    return e0().getValue();
169  }
170
171  protected final K k1() {
172    return e1().getKey();
173  }
174
175  protected final V v1() {
176    return e1().getValue();
177  }
178
179  protected final K k2() {
180    return e2().getKey();
181  }
182
183  protected final V v2() {
184    return e2().getValue();
185  }
186
187  protected final K k3() {
188    return e3().getKey();
189  }
190
191  protected final V v3() {
192    return e3().getValue();
193  }
194
195  protected final K k4() {
196    return e4().getKey();
197  }
198
199  protected final V v4() {
200    return e4().getValue();
201  }
202}