/* * Aphelion * Copyright (c) 2014 Joris van der Wel * * This file is part of Aphelion * * Aphelion is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3 of the License. * * Aphelion is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Aphelion. If not, see <http://www.gnu.org/licenses/>. * * In addition, the following supplemental terms apply, based on section 7 of * the GNU Affero General Public License (version 3): * a) Preservation of all legal notices and author attributions * b) Prohibition of misrepresentation of the origin of this material, and * modified versions are required to be marked in reasonable ways as * different from the original version * * Linking this library statically or dynamically with other modules is making a * combined work based on this library. Thus, the terms and conditions of the * GNU Affero General Public License cover the whole combination. * * As a special exception, the copyright holders of this library give you * permission to link this library with independent modules to produce an * executable, regardless of the license terms of these independent modules, * and to copy and distribute the resulting executable under terms of your * choice, provided that you also meet, for each linked independent module, * the terms and conditions of the license of that module. An independent * module is a module which is not derived from or based on this library. */ package aphelion.shared.swissarmyknife; import aphelion.shared.physics.valueobjects.PhysicsPoint; import java.util.Iterator; import java.util.NoSuchElementException; import org.junit.Test; import static org.junit.Assert.*; import org.junit.Before; /** * * @author joris */ public class EntityGridTest { private EntityGrid<MyEntity> grid; @Before public void setUp() { grid = new EntityGrid<>(32768, 1024 * 16 * 1024 / 32768); } @Test public void testSingle() { MyEntity a = new MyEntity("a"); grid.updateLocation(a, 0, 0); assertContains("position 0,0 should be stored in cell 0, 0", a, cellLow(0, 0), cellHigh(0, 0)); grid.updateLocation(a, 32768, 0); assertNotContains("position 32768,0 should not be stored in cell 0, 0", a, cellLow(0, 0), cellHigh(0, 0)); assertContains("position 32768,0 should be stored in cell 1, 0", a, cellLow(1, 0), cellHigh(1, 0)); grid.updateLocation(a, 32768 * 3 - 1, 0); assertNotContains("position 32768 * 3 - 1, 0 should not be stored in cell 0, 0", a, cellLow(0, 0), cellHigh(0, 0)); assertNotContains("position 32768 * 3 - 1, 0 should not be stored in cell 0, 1", a, cellLow(0, 1), cellHigh(0, 1)); assertNotContains("position 32768 * 3 - 1, 0 should not be stored in cell 1, 0", a, cellLow(1, 0), cellHigh(1, 0)); assertContains("position 32768 * 3 - 1, 0 should be stored in cell 2, 0", a, cellLow(2, 0), cellHigh(2, 0)); assertContains("position 32768 * 3 - 1, 0 should be between cell 1,0 and 3,3", a, cellLow(1, 0), cellHigh(3, 3)); } @Test public void testEmptyIterator() { Iterator it = grid.iterator(new PhysicsPoint(0,0), new PhysicsPoint(0,0)); assertFalse(it.hasNext()); try { it.next(); assertTrue("Should throw", false); } catch (NoSuchElementException ex) { assertTrue(true); } } @Test public void testIteratorRemove() { MyEntity a = new MyEntity("a"); grid.updateLocation(a, 0, 0); Iterator it = grid.iterator(cellLow(0, 0), cellHigh(0, 0)); assertNotNull(it.next()); try { it.remove(); assertTrue("Should throw", false); } catch (UnsupportedOperationException ex) { assertTrue(true); } } @Test public void testNegative() { MyEntity a = new MyEntity("a"); grid.updateLocation(a, -32768, 0); assertEmpty("negative positions should be ignored", new PhysicsPoint(0, 0), new PhysicsPoint(40000, 40000)); grid.updateLocation(a, -32767, 0); assertContains("negative position >= CELL_SIZE should be interpreted as 0 (documented caveat)", a, new PhysicsPoint(0, 0), new PhysicsPoint(40000, 40000)); } @Test public void testMultiple() { MyEntity a = new MyEntity("a"); MyEntity b = new MyEntity("b"); MyEntity c = new MyEntity("c"); MyEntity d = new MyEntity("d"); grid.updateLocation(a, 4000, 10000); grid.updateLocation(b, new PhysicsPoint(2320, 11230)); grid.updateLocation(c, 40323, 51230); grid.updateLocation(d, 32768*15, 32768*15); assertContains("Should contain a", a, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain b", b, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain c", c, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain d", d, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain a", a, cellLow(2, 2), 1); assertNotContains("Should contain b", b, cellLow(2, 2), 1); assertContains("Should contain c", c, cellLow(2, 2), 1); assertNotContains("Should not contain d", d, cellLow(2, 2), 1); grid.updateLocation(a, null); grid.updateLocation(b, new PhysicsPoint()); // unset assertNotContains("Should not contain a", a, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain b", b, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain c", c, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain d", d, cellLow(0, 0), cellHigh(3, 3)); } @Test public void testQueue() { MyEntity a = new MyEntity("a"); MyEntity b = new MyEntity("b"); MyEntity c = new MyEntity("c"); MyEntity d = new MyEntity("d"); grid.enableQueue(); grid.updateLocation(a, 4000, 10000); grid.removeEntity(a); grid.updateLocation(a, 4000, 10000); grid.updateLocation(b, 2320, 11230); grid.updateLocation(c, new PhysicsPoint(40323, 11230)); grid.updateLocation(d, 32768*15, 32768*15); grid.updateLocation(b, null); assertNotContains("Should not contain a", a, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain b", b, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain c", c, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain d", d, cellLow(0, 0), cellHigh(3, 3)); grid.disableQueue(); assertContains("Should contain a", a, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain b", b, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain c", c, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain d", d, cellLow(0, 0), cellHigh(3, 3)); // should take effect immediately grid.updateLocation(b, 2320, 11230); assertContains("Should contain b", b, cellLow(0, 0), cellHigh(3, 3)); grid.enableQueue(); grid.updateLocation(a, new PhysicsPoint()); // unset grid.disableQueue(); assertNotContains("Should contain a", a, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain b", b, cellLow(0, 0), cellHigh(3, 3)); assertContains("Should contain c", c, cellLow(0, 0), cellHigh(3, 3)); assertNotContains("Should not contain d", d, cellLow(0, 0), cellHigh(3, 3)); } @Test public void testQueueIllegalState() { try { grid.disableQueue(); assertTrue("Should throw", false); } catch (IllegalStateException ex) { assertTrue(true); } grid.enableQueue(); try { grid.enableQueue(); assertTrue("Should throw", false); } catch (IllegalStateException ex) { assertTrue(true); } grid.disableQueue(); try { grid.disableQueue(); assertTrue("Should throw", false); } catch (IllegalStateException ex) { assertTrue(true); } } private PhysicsPoint cellLow(int x, int y) { return new PhysicsPoint(x * 32768, y * 32768); } private PhysicsPoint cellHigh(int x, int y) { return new PhysicsPoint(x * 32768 + 32767, y * 32768 + 32767); } private void assertEmpty(String message, PhysicsPoint low, PhysicsPoint high) { Iterator<MyEntity> it = grid.iterator(low, high); assertFalse(message, it.hasNext()); } private void assertContains(String message, MyEntity first, PhysicsPoint low, PhysicsPoint high) { Iterator<MyEntity> it = grid.iterator(low, high); while (it.hasNext()) { MyEntity en = it.next(); if (en == first) { return; } } assertTrue(message, false); } private void assertNotContains(String message, MyEntity first, PhysicsPoint low, PhysicsPoint high) { Iterator<MyEntity> it = grid.iterator(low, high); while (it.hasNext()) { MyEntity en = it.next(); if (en == first) { assertTrue(message, false); } } } private void assertEmpty(String message, PhysicsPoint center, int radius) { Iterator<MyEntity> it = grid.iterator(center, radius); assertFalse(message, it.hasNext()); } private void assertContains(String message, MyEntity first, PhysicsPoint center, int radius) { Iterator<MyEntity> it = grid.iterator(center, radius); while (it.hasNext()) { MyEntity en = it.next(); if (en == first) { return; } } assertTrue(message, false); } private void assertNotContains(String message, MyEntity first, PhysicsPoint center, int radius) { Iterator<MyEntity> it = grid.iterator(center, radius); while (it.hasNext()) { MyEntity en = it.next(); if (en == first) { assertTrue(message, false); } } } private class MyEntity implements EntityGridEntity { private final LinkedListEntry entry = new LinkedListEntry(this); public final String data; MyEntity(String data) { this.data = data; } @Override public LinkedListEntry getEntityGridEntry(EntityGrid grid) { return entry; } @Override public String toString() { return "MyEntity " + data; } } }