001/* 002 * Copyright (C) 2008 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.testers; 018 019import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES; 020import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE; 021import static com.google.common.collect.testing.features.CollectionSize.ONE; 022import static com.google.common.collect.testing.features.CollectionSize.ZERO; 023import static java.util.Arrays.asList; 024import static java.util.Collections.singleton; 025import static org.junit.Assert.assertThrows; 026 027import com.google.common.annotations.GwtCompatible; 028import com.google.common.collect.testing.AbstractCollectionTester; 029import com.google.common.collect.testing.MinimalCollection; 030import com.google.common.collect.testing.features.CollectionFeature; 031import com.google.common.collect.testing.features.CollectionSize; 032import java.util.Collection; 033import java.util.List; 034 035/** 036 * A generic JUnit test which tests {@code retainAll} operations on a collection. Can't be invoked 037 * directly; please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}. 038 * 039 * @author Chris Povirk 040 */ 041@GwtCompatible 042public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> { 043 044 /** A collection of elements to retain, along with a description for use in failure messages. */ 045 private final class Target { 046 private final Collection<E> toRetain; 047 private final String description; 048 049 private Target(Collection<E> toRetain, String description) { 050 this.toRetain = toRetain; 051 this.description = description; 052 } 053 054 @Override 055 public String toString() { 056 return description; 057 } 058 } 059 060 private Target empty; 061 private Target disjoint; 062 private Target superset; 063 private Target nonEmptyProperSubset; 064 private Target sameElements; 065 private Target partialOverlap; 066 private Target containsDuplicates; 067 private Target nullSingleton; 068 069 @Override 070 public void setUp() throws Exception { 071 super.setUp(); 072 073 empty = new Target(emptyCollection(), "empty"); 074 /* 075 * We test that nullSingleton.retainAll(disjointList) does NOT throw a 076 * NullPointerException when disjointList does not, so we can't use 077 * MinimalCollection, which throws NullPointerException on calls to 078 * contains(null). 079 */ 080 List<E> disjointList = asList(e3(), e4()); 081 disjoint = new Target(disjointList, "disjoint"); 082 superset = new Target(MinimalCollection.of(e0(), e1(), e2(), e3(), e4()), "superset"); 083 nonEmptyProperSubset = new Target(MinimalCollection.of(e1()), "subset"); 084 sameElements = new Target(asList(createSamplesArray()), "sameElements"); 085 containsDuplicates = 086 new Target(MinimalCollection.of(e0(), e0(), e3(), e3()), "containsDuplicates"); 087 partialOverlap = new Target(MinimalCollection.of(e2(), e3()), "partialOverlap"); 088 nullSingleton = new Target(singleton(null), "nullSingleton"); 089 } 090 091 // retainAll(empty) 092 093 @CollectionFeature.Require(SUPPORTS_REMOVE) 094 @CollectionSize.Require(ZERO) 095 public void testRetainAll_emptyPreviouslyEmpty() { 096 expectReturnsFalse(empty); 097 expectUnchanged(); 098 } 099 100 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 101 @CollectionSize.Require(ZERO) 102 public void testRetainAll_emptyPreviouslyEmptyUnsupported() { 103 expectReturnsFalseOrThrows(empty); 104 expectUnchanged(); 105 } 106 107 @CollectionFeature.Require(SUPPORTS_REMOVE) 108 @CollectionSize.Require(absent = ZERO) 109 public void testRetainAll_emptyPreviouslyNonEmpty() { 110 expectReturnsTrue(empty); 111 expectContents(); 112 expectMissing(e0(), e1(), e2()); 113 } 114 115 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 116 @CollectionSize.Require(absent = ZERO) 117 public void testRetainAll_emptyPreviouslyNonEmptyUnsupported() { 118 expectThrows(empty); 119 expectUnchanged(); 120 } 121 122 // retainAll(disjoint) 123 124 @CollectionFeature.Require(SUPPORTS_REMOVE) 125 @CollectionSize.Require(ZERO) 126 public void testRetainAll_disjointPreviouslyEmpty() { 127 expectReturnsFalse(disjoint); 128 expectUnchanged(); 129 } 130 131 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 132 @CollectionSize.Require(ZERO) 133 public void testRetainAll_disjointPreviouslyEmptyUnsupported() { 134 expectReturnsFalseOrThrows(disjoint); 135 expectUnchanged(); 136 } 137 138 @CollectionFeature.Require(SUPPORTS_REMOVE) 139 @CollectionSize.Require(absent = ZERO) 140 public void testRetainAll_disjointPreviouslyNonEmpty() { 141 expectReturnsTrue(disjoint); 142 expectContents(); 143 expectMissing(e0(), e1(), e2()); 144 } 145 146 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 147 @CollectionSize.Require(absent = ZERO) 148 public void testRetainAll_disjointPreviouslyNonEmptyUnsupported() { 149 expectThrows(disjoint); 150 expectUnchanged(); 151 } 152 153 // retainAll(superset) 154 155 @CollectionFeature.Require(SUPPORTS_REMOVE) 156 public void testRetainAll_superset() { 157 expectReturnsFalse(superset); 158 expectUnchanged(); 159 } 160 161 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 162 public void testRetainAll_supersetUnsupported() { 163 expectReturnsFalseOrThrows(superset); 164 expectUnchanged(); 165 } 166 167 // retainAll(subset) 168 169 @CollectionFeature.Require(SUPPORTS_REMOVE) 170 @CollectionSize.Require(absent = {ZERO, ONE}) 171 public void testRetainAll_subset() { 172 expectReturnsTrue(nonEmptyProperSubset); 173 expectContents(nonEmptyProperSubset.toRetain); 174 } 175 176 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 177 @CollectionSize.Require(absent = {ZERO, ONE}) 178 public void testRetainAll_subsetUnsupported() { 179 expectThrows(nonEmptyProperSubset); 180 expectUnchanged(); 181 } 182 183 // retainAll(sameElements) 184 185 @CollectionFeature.Require(SUPPORTS_REMOVE) 186 public void testRetainAll_sameElements() { 187 expectReturnsFalse(sameElements); 188 expectUnchanged(); 189 } 190 191 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 192 public void testRetainAll_sameElementsUnsupported() { 193 expectReturnsFalseOrThrows(sameElements); 194 expectUnchanged(); 195 } 196 197 // retainAll(partialOverlap) 198 199 @CollectionFeature.Require(SUPPORTS_REMOVE) 200 @CollectionSize.Require(absent = {ZERO, ONE}) 201 public void testRetainAll_partialOverlap() { 202 expectReturnsTrue(partialOverlap); 203 expectContents(e2()); 204 } 205 206 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 207 @CollectionSize.Require(absent = {ZERO, ONE}) 208 public void testRetainAll_partialOverlapUnsupported() { 209 expectThrows(partialOverlap); 210 expectUnchanged(); 211 } 212 213 // retainAll(containsDuplicates) 214 215 @CollectionFeature.Require(SUPPORTS_REMOVE) 216 @CollectionSize.Require(ONE) 217 public void testRetainAll_containsDuplicatesSizeOne() { 218 expectReturnsFalse(containsDuplicates); 219 expectContents(e0()); 220 } 221 222 @CollectionFeature.Require(SUPPORTS_REMOVE) 223 @CollectionSize.Require(absent = {ZERO, ONE}) 224 public void testRetainAll_containsDuplicatesSizeSeveral() { 225 expectReturnsTrue(containsDuplicates); 226 expectContents(e0()); 227 } 228 229 // retainAll(nullSingleton) 230 231 @CollectionFeature.Require(SUPPORTS_REMOVE) 232 @CollectionSize.Require(ZERO) 233 public void testRetainAll_nullSingletonPreviouslyEmpty() { 234 expectReturnsFalse(nullSingleton); 235 expectUnchanged(); 236 } 237 238 @CollectionFeature.Require(SUPPORTS_REMOVE) 239 @CollectionSize.Require(absent = ZERO) 240 public void testRetainAll_nullSingletonPreviouslyNonEmpty() { 241 expectReturnsTrue(nullSingleton); 242 expectContents(); 243 } 244 245 @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES}) 246 @CollectionSize.Require(ONE) 247 public void testRetainAll_nullSingletonPreviouslySingletonWithNull() { 248 initCollectionWithNullElement(); 249 expectReturnsFalse(nullSingleton); 250 expectContents(createArrayWithNullElement()); 251 } 252 253 @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES}) 254 @CollectionSize.Require(absent = {ZERO, ONE}) 255 public void testRetainAll_nullSingletonPreviouslySeveralWithNull() { 256 initCollectionWithNullElement(); 257 expectReturnsTrue(nullSingleton); 258 expectContents(nullSingleton.toRetain); 259 } 260 261 // nullSingleton.retainAll() 262 263 @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES}) 264 @CollectionSize.Require(absent = ZERO) 265 public void testRetainAll_containsNonNullWithNull() { 266 initCollectionWithNullElement(); 267 expectReturnsTrue(disjoint); 268 expectContents(); 269 } 270 271 // retainAll(null) 272 273 /* 274 * AbstractCollection fails the retainAll(null) test when the subject 275 * collection is empty, but we'd still like to test retainAll(null) when we 276 * can. We split the test into empty and non-empty cases. This allows us to 277 * suppress only the former. 278 */ 279 280 @CollectionFeature.Require(SUPPORTS_REMOVE) 281 @CollectionSize.Require(ZERO) 282 public void testRetainAll_nullCollectionReferenceEmptySubject() { 283 try { 284 collection.retainAll(null); 285 // Returning successfully is not ideal, but tolerated. 286 } catch (NullPointerException tolerated) { 287 } 288 } 289 290 @CollectionFeature.Require(SUPPORTS_REMOVE) 291 @CollectionSize.Require(absent = ZERO) 292 public void testRetainAll_nullCollectionReferenceNonEmptySubject() { 293 assertThrows(NullPointerException.class, () -> collection.retainAll(null)); 294 } 295 296 private void expectReturnsTrue(Target target) { 297 String message = Platform.format("retainAll(%s) should return true", target); 298 assertTrue(message, collection.retainAll(target.toRetain)); 299 } 300 301 private void expectReturnsFalse(Target target) { 302 String message = Platform.format("retainAll(%s) should return false", target); 303 assertFalse(message, collection.retainAll(target.toRetain)); 304 } 305 306 private void expectThrows(Target target) { 307 assertThrows(UnsupportedOperationException.class, () -> collection.retainAll(target.toRetain)); 308 } 309 310 private void expectReturnsFalseOrThrows(Target target) { 311 String message = Platform.format("retainAll(%s) should return false or throw", target); 312 try { 313 assertFalse(message, collection.retainAll(target.toRetain)); 314 } catch (UnsupportedOperationException tolerated) { 315 } 316 } 317}