/* * Copyright (C) 2012 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.collections.specialized; import com.facebook.util.ExtRunnable; import com.facebook.util.TimeUtil; import com.facebook.util.digest.LongMurmur3Hash; import org.testng.Assert; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Iterator; import java.util.Random; import java.util.Set; public class TestColtHashSet { private ColtLongHashSet set; private int numElements; @BeforeMethod(alwaysRun = true) public void setUp() throws Exception { numElements = 10; set = new ColtLongHashSet(numElements); } @Test(groups = "fast") public void testAdd() throws Exception { Assert.assertEquals(set.size(), 0); Assert.assertTrue(set.add(100L)); Assert.assertTrue(set.contains(100L)); Assert.assertEquals(set.size(), 1); Assert.assertFalse(set.add(100L)); Assert.assertEquals(set.size(), 1); Assert.assertTrue(set.add(200L)); Assert.assertTrue(set.contains(100L)); Assert.assertTrue(set.contains(200L)); Assert.assertEquals(set.size(), 2); } @Test(groups = "fast") public void testIsEmpty() throws Exception { Assert.assertTrue(set.isEmpty()); Assert.assertTrue(set.add(100L)); Assert.assertFalse(set.isEmpty()); } @Test(groups = "fast") public void testNotThere() throws Exception { Assert.assertEquals(set.size(), 0); Assert.assertTrue(set.add(100L)); Assert.assertFalse(set.contains(10L)); } @Test(groups = "fast") public void testRemove() throws Exception { Assert.assertTrue(set.add(1L)); Assert.assertTrue(set.remove(1L)); Assert.assertFalse(set.remove(1L)); } @Test(groups = "fast") public void testResize() throws Exception { fillSet(); Assert.assertEquals(set.size(), numElements); } @Test(groups = "fast") public void testConcurrentModifcation() throws Exception { set.add(1L); Iterator<Long> iterator = set.iterator(); Assert.assertTrue(iterator.hasNext()); set.add(1L); Assert.assertTrue(iterator.hasNext()); set.add(2L); // only changing the set should cause this try { iterator.hasNext(); } catch (Exception e) { Assert.assertTrue(e instanceof ConcurrentModificationException); } } @Test(groups = "fast") public void testIterator() throws Exception { set.add(1L); set.add(2L); set.add(3L); Iterator<Long> iterator = set.iterator(); Assert.assertTrue(iterator.hasNext()); Assert.assertEquals(iterator.next().longValue(), 3L); Assert.assertTrue(iterator.hasNext()); Assert.assertEquals(iterator.next().longValue(), 2L); Assert.assertTrue(iterator.hasNext()); Assert.assertEquals(iterator.next().longValue(), 1L); Assert.assertFalse(iterator.hasNext()); } @Test(groups = "fast") public void testIteratorWhenFull() throws Exception { fillSet(); int count = 0; Iterator<Long> iterator = set.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); count++; } Assert.assertEquals(set.size(), 0); Assert.assertEquals(count, numElements); Iterator<Long> iterator2 = set.iterator(); // now an iterator shouldn't have any values in it Assert.assertFalse(iterator2.hasNext()); } @Test(groups = "fast") public void testIterateAndRemove() throws Exception { Set<Long> answer = new HashSet<Long>(); answer.add(1L); answer.add(2L); set.add(1L); set.add(2L); Iterator<Long> iterator = set.iterator(); if (iterator.hasNext()) { // remove from answer for check below answer.remove(iterator.next()); iterator.remove(); } Assert.assertTrue(iterator.hasNext()); // check that whatever value we removed, the other one is still present Assert.assertEquals( iterator.next().longValue(), answer.iterator().next().longValue() ); } @Test(groups = "fast") public void testRepeatedRemove() throws Exception { set.add(1L); Iterator<Long> iterator = set.iterator(); iterator.next(); iterator.remove(); try { iterator.remove(); Assert.fail("expected exception"); } catch (Exception e) { Assert.assertTrue(e instanceof IllegalStateException); } } @Test(groups = "fast") public void testRemoveWithoutNext() throws Exception { set.add(1L); Iterator<Long> iterator = set.iterator(); try { iterator.remove(); Assert.fail("expected exception"); } catch (Exception e) { Assert.assertTrue(e instanceof IllegalStateException); } } @Test(groups = "fast") public void testStress() throws Exception { // sanity test that exercises LongHashSet2 and LongLinkedList int inserts = 100000; int maxSize = 8000; SampledSet<Long> set = new SampledSetImpl<>( maxSize, new LongMurmur3Hash(), new LongHashSetFactory(maxSize) ); timeAdds("custom-long-hash-set-2", set, inserts); } private static void timeAdds(String tag, final Set<Long> set, final int numAdds) throws Exception { TimeUtil.logElapsedTime(tag, new ExtRunnable<Exception>() { @Override public void run() throws Exception { Random random = new Random(); for (int i = 0; i < numAdds; i++) { set.add(Math.abs(random.nextLong())); } } }); } private void fillSet() { for (int i = 0; i < numElements; i++) { Assert.assertTrue(set.add((long) i)); } } private void emptySet() { for (int i = 0; i < numElements; i++) { Assert.assertTrue(set.remove((long) i)); } Assert.assertEquals(set.size(), 0); Assert.assertTrue(set.isEmpty()); } private void checkFullSet() { Assert.assertEquals(set.size(), numElements); for (int i = 0; i < numElements; i++) { Assert.assertTrue(set.contains((long) i)); } } }