/** * PermissionsEx * Copyright (C) zml and PermissionsEx contributors * * 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 ninja.leaping.permissionsex.backend.sql; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import ninja.leaping.configurate.objectmapping.ObjectMappingException; import ninja.leaping.permissionsex.PermissionsExTest; import ninja.leaping.permissionsex.backend.DataStore; import ninja.leaping.permissionsex.config.PermissionsExConfiguration; import ninja.leaping.permissionsex.exception.PEBKACException; import ninja.leaping.permissionsex.exception.PermissionsLoadingException; import ninja.leaping.permissionsex.rank.RankLadder; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.*; @SuppressWarnings("OptionalGetWithoutIsPresent") @RunWith(Parameterized.class) public class SqlDaoTest extends PermissionsExTest { private static final AtomicInteger COUNTER = new AtomicInteger(); @Parameterized.Parameters(name = "{0}") public static Iterable<Object> data() { String[] propertyTestDbs = System.getProperty("ninja.leaping.permissionsex.backend.sql.testDatabases", "").split(";", -1); if (propertyTestDbs.length == 1 && propertyTestDbs[0].equals("")) { propertyTestDbs = new String[0]; } final Object[][] tests = new Object[propertyTestDbs.length + 1][2]; tests[propertyTestDbs.length] = new Object[] {"h2", "jdbc:h2:{base}/test.db"}; for (int i = 0; i < propertyTestDbs.length; ++i) { tests[i] = propertyTestDbs[i].split("!"); } return Arrays.asList((Object[]) tests); } private final SqlDataStore sqlStore = new SqlDataStore(); private String jdbcUrl; public SqlDaoTest(String databaseName, String jdbcUrl) throws IOException { this.jdbcUrl = jdbcUrl; } @Before @Override public void setUp() throws IOException, PEBKACException, PermissionsLoadingException, ObjectMappingException { File testDir = tempFolder.newFolder(); jdbcUrl = jdbcUrl.replaceAll("\\{base\\}", testDir.getCanonicalPath()); sqlStore.setConnectionUrl(jdbcUrl); sqlStore.setPrefix("pextest" + COUNTER.getAndIncrement()); super.setUp(); } @After @Override public void tearDown() { // Delete all created tables; try (Connection conn = sqlStore.getDataSource().getConnection()) { ResultSet tables = conn.getMetaData().getTables(null, null, "PEXTEST%", null); Statement stmt = conn.createStatement(); while (tables.next()) { stmt.addBatch("DROP TABLE " + tables.getString("TABLE_NAME")); } stmt.executeBatch(); } catch (SQLException e) { throw new RuntimeException(e); } super.tearDown(); } @Override protected PermissionsExConfiguration populate() { return new PermissionsExConfiguration() { @Override public DataStore getDataStore(String name) { return null; } @Override public DataStore getDefaultDataStore() { return sqlStore; } @Override public boolean isDebugEnabled() { return false; } @Override public List<String> getServerTags() { return ImmutableList.of(); } @Override public void validate() throws PEBKACException { } @Override public PermissionsExConfiguration reload() throws IOException { return this; } }; } @Test public void testGlobalParameters() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { assertFalse(dao.getGlobalParameter("nonexistant").isPresent()); dao.setGlobalParameter("potato", "russet"); assertEquals("russet", dao.getGlobalParameter("potato").get()); dao.setGlobalParameter("potato", "sweet"); assertEquals("sweet", dao.getGlobalParameter("potato").get()); dao.setGlobalParameter("potato", null); assertFalse(dao.getGlobalParameter("potato").isPresent()); } } @Test public void testGetSubjectRef() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { assertFalse(dao.getSubjectRef("group", "admin").isPresent()); assertFalse(dao.getSubjectRef(1).isPresent()); } } @Test public void testGetOrCreateSubjectRef() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { assertFalse(dao.getSubjectRef("group", "admin").isPresent()); SubjectRef created = dao.getOrCreateSubjectRef("group", "admin"); SubjectRef fetched = dao.getSubjectRef("group", "admin").get(); assertEquals(created.getId(), fetched.getId()); SubjectRef couldBeCreated = dao.getOrCreateSubjectRef("group", "admin"); assertEquals(created.getId(), couldBeCreated.getId()); SubjectRef gottenById = dao.getSubjectRef(created.getId()).get(); assertEquals(created.getId(), gottenById.getId()); assertEquals(created, gottenById); } } @Test public void testRemoveSubject() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { SubjectRef first = dao.getOrCreateSubjectRef("group", "one"); SubjectRef second = dao.getOrCreateSubjectRef("group", "two"); assertTrue(dao.removeSubject("group", "one")); assertFalse(dao.getSubjectRef(first.getType(), first.getIdentifier()).isPresent()); assertTrue(dao.removeSubject(second)); assertFalse(dao.getSubjectRef(second.getId()).isPresent()); } } @Test public void getRegisteredTypes() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { dao.getOrCreateSubjectRef("group", "one"); dao.getOrCreateSubjectRef("group", "two"); dao.getOrCreateSubjectRef("user", UUID.randomUUID().toString()); dao.getOrCreateSubjectRef("default", "user"); dao.getOrCreateSubjectRef("system", "console"); assertEquals(ImmutableSet.of("group", "user", "default", "system"), dao.getRegisteredTypes()); } } @Test public void getAllIdentifiers() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { dao.getOrCreateSubjectRef("group", "one"); dao.getOrCreateSubjectRef("group", "two"); dao.getOrCreateSubjectRef("default", "user"); dao.getOrCreateSubjectRef("default", "default"); dao.getOrCreateSubjectRef("system", "console"); assertEquals(ImmutableSet.of("one", "two"), dao.getAllIdentifiers("group")); assertEquals(ImmutableSet.of("user", "default"), dao.getAllIdentifiers("default")); } } @Test public void testAddRemoveSegment() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { SubjectRef subject = dao.getOrCreateSubjectRef("group", "one"); assertTrue(dao.getSegments(subject).isEmpty()); Segment seg = dao.addSegment(subject); List<Segment> segments = dao.getSegments(subject); assertFalse(segments.isEmpty()); assertEquals(seg.getId(), segments.get(0).getId()); assertTrue(dao.removeSegment(seg)); assertTrue(dao.getSegments(subject).isEmpty()); } } @Test public void testContexts() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { final SubjectRef subject = dao.getOrCreateSubjectRef("test", "contexts"); Segment testSeg = dao.addSegment(subject); assertTrue(testSeg.getContexts().isEmpty()); final Set<Entry<String, String>> contexts = ImmutableSet.of(Maps.immutableEntry("world", "DIM-1"), Maps.immutableEntry("server-tag", "minigames")); dao.setContexts(testSeg, contexts); testSeg = dao.getSegments(subject).get(0); assertEquals(contexts, testSeg.getContexts()); dao.setContexts(testSeg, ImmutableSet.of()); testSeg = dao.getSegments(subject).get(0); assertTrue(testSeg.getContexts().isEmpty()); } } @Test public void testOptions() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { SubjectRef subject = dao.getOrCreateSubjectRef("group", "one"); Segment seg = dao.addSegment(subject); assertFalse(seg.getOptions().containsKey("test")); // Set individually dao.setOption(seg, "test", "potato"); dao.setOption(seg, "test2", "orange"); dao.setOption(seg, "test", "pear"); seg = dao.getSegments(subject).get(0); // Probably not the most efficient, but having extra code paths just for testing is a bad idea (maybe a get options/etc?) assertEquals("pear", seg.getOptions().get("test")); assertEquals("orange", seg.getOptions().get("test2")); // Bulk set dao.setOptions(seg, ImmutableMap.of("direction", "left", "speed", "vroom")); seg = dao.getSegments(subject).get(0); assertFalse(seg.getOptions().containsKey("test")); assertFalse(seg.getOptions().containsKey("test2")); assertEquals("left", seg.getOptions().get("direction")); assertEquals("vroom", seg.getOptions().get("speed")); // Clear a single option dao.clearOption(seg, "direction"); seg = dao.getSegments(subject).get(0); assertFalse(seg.getOptions().containsKey("direction")); assertEquals("vroom", seg.getOptions().get("speed")); // Working through the Segment object seg = seg.withOption("test", "potato") .withOption("direction", "north"); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals("potato", seg.getOptions().get("test")); assertEquals("vroom", seg.getOptions().get("speed")); assertEquals("north", seg.getOptions().get("direction")); seg = seg.withoutOptions(); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertTrue(seg.getOptions().isEmpty()); seg = seg.withOptions(ImmutableMap.of("absorbency", "high", "color", "yellow")); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals("high", seg.getOptions().get("absorbency")); assertEquals("yellow", seg.getOptions().get("color")); seg = seg.withOptions(ImmutableMap.of("absorbency", "high", "color", "yellow")) .withoutOptions() .withOption("test", "orange"); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals(1, seg.getOptions().size()); assertEquals("orange", seg.getOptions().get("test")); } } @Test public void testPermissions() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { SubjectRef subject = dao.getOrCreateSubjectRef("group", "one"); Segment seg = dao.addSegment(subject); assertFalse(seg.getPermissions().containsKey("test.first")); // Set individually dao.setPermission(seg, "test.first", 1); dao.setPermission(seg, "test.second", 5); dao.setPermission(seg, "test.first", -1); seg = dao.getSegments(subject).get(0); // Probably not the most efficient, but having extra code paths just for testing is a bad idea (maybe a get options/etc?) assertEquals(-1, seg.getPermissions().get("test.first").intValue()); assertEquals(5, seg.getPermissions().get("test.second").intValue()); // Bulk set dao.setPermissions(seg, ImmutableMap.of("test.steering", 1, "test.acceleration", -1)); seg = dao.getSegments(subject).get(0); assertFalse(seg.getPermissions().containsKey("test.first")); assertFalse(seg.getPermissions().containsKey("test.second")); assertEquals(1, seg.getPermissions().get("test.steering").intValue()); assertEquals(-1, seg.getPermissions().get("test.acceleration").intValue()); // Clear a single option dao.clearPermission(seg, "test.steering"); seg = dao.getSegments(subject).get(0); assertFalse(seg.getPermissions().containsKey("test.steering")); assertEquals(-1, seg.getPermissions().get("test.acceleration").intValue()); // Working through the Segment object seg = seg.withPermission("test.first", -2) .withPermission("test.steering", 1); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals(-2, seg.getPermissions().get("test.first").intValue()); assertEquals(-1, seg.getPermissions().get("test.acceleration").intValue()); assertEquals(1, seg.getPermissions().get("test.steering").intValue()); seg = seg.withoutPermissions(); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertTrue(seg.getPermissions().isEmpty()); seg = seg.withPermissions(ImmutableMap.of("test.absorb", 42, "test.color.change", -4)); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals(42, seg.getPermissions().get("test.absorb").intValue()); assertEquals(-4, seg.getPermissions().get("test.color.change").intValue()); seg = seg.withPermissions(ImmutableMap.of("test.absorb", 42, "test.color.change", -4)) .withoutPermissions() .withPermission("test.first", 2); seg.doUpdates(dao); seg = dao.getSegments(subject).get(0); assertEquals(1, seg.getPermissions().size()); assertEquals(2, seg.getPermissions().get("test.first").intValue()); } } @Test public void testParents() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { final SubjectRef member = dao.getOrCreateSubjectRef("group", "member"), vip = dao.getOrCreateSubjectRef("group", "vip"), potato = dao.getOrCreateSubjectRef("group", "potato"), guest = dao.getOrCreateSubjectRef("group", "guest"), novice = dao.getOrCreateSubjectRef("group", "novice"); Segment vipSeg = dao.addSegment(vip); assertTrue(vipSeg.getParents().isEmpty()); dao.addParent(vipSeg, member); vipSeg = dao.getSegments(vip).get(0); assertTrue(vipSeg.getParents().contains(member)); dao.removeParent(vipSeg, member); vipSeg = dao.getSegments(vip).get(0); assertEquals(0, vipSeg.getParents().size()); dao.setParents(vipSeg, ImmutableList.of(guest, novice)); vipSeg = dao.getSegments(vip).get(0); assertEquals(2, vipSeg.getParents().size()); assertTrue(vipSeg.getParents().contains(guest)); assertTrue(vipSeg.getParents().contains(novice)); vipSeg = vipSeg.withoutParents(); vipSeg.doUpdates(dao); vipSeg = dao.getSegments(vip).get(0); assertEquals(0, vipSeg.getParents().size()); vipSeg = vipSeg.withAddedParent(potato); vipSeg.doUpdates(dao); vipSeg = dao.getSegments(vip).get(0); assertEquals(1, vipSeg.getParents().size()); assertTrue(vipSeg.getParents().contains(potato)); vipSeg = vipSeg.withAddedParent(member); vipSeg.doUpdates(dao); vipSeg = dao.getSegments(vip).get(0); assertEquals(2, vipSeg.getParents().size()); assertTrue(vipSeg.getParents().contains(potato)); assertTrue(vipSeg.getParents().contains(member)); final SubjectRef unallocatedGroup = SubjectRef.unresolved("group", "unresolved"); assertTrue(unallocatedGroup.isUnallocated()); // Test unallocated dao.addParent(vipSeg, unallocatedGroup); assertFalse(unallocatedGroup.isUnallocated()); vipSeg = dao.getSegments(vip).get(0); assertTrue(vipSeg.getParents().contains(unallocatedGroup)); } } @Test public void testSetDefaultValue() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { final SubjectRef subject = dao.getOrCreateSubjectRef("test", "defvalue"); Segment newSeg = Segment.unallocated().withDefaultValue(5); dao.allocateSegment(subject, newSeg); Segment testSeg = dao.getSegments(subject).get(0); assertEquals(5, testSeg.getPermissionDefault().intValue()); testSeg = testSeg.withDefaultValue(-4); testSeg.doUpdates(dao); testSeg = dao.getSegments(subject).get(0); assertEquals(-4, testSeg.getPermissionDefault().intValue()); testSeg = testSeg.withDefaultValue(null); testSeg.doUpdates(dao); testSeg = dao.getSegments(subject).get(0); assertEquals(null, testSeg.getPermissionDefault()); } } @Test public void testContextInheritance() throws SQLException { final Entry<String, String> worldNether = Maps.immutableEntry("world", "DIM-1"), serverMinigames = Maps.immutableEntry("server-tag", "minigames"); final List<Entry<String, String>> worldNetherParents = ImmutableList.of(Maps.immutableEntry("world", "world")), serverTagMinigamesParents = ImmutableList.of(Maps.immutableEntry("server-tag", "adventure"), Maps.immutableEntry("world", "minigames")); try (SqlDao dao = sqlStore.getDao()) { // resolve, set, set to null, add new SqlContextInheritance inherit = dao.getContextInheritance(); assertTrue(inherit.getAllParents().isEmpty()); dao.setContextInheritance(worldNether, worldNetherParents); inherit = dao.getContextInheritance(); assertEquals(worldNetherParents, inherit.getParents(worldNether)); inherit = inherit.setParents(serverMinigames, serverTagMinigamesParents); inherit.doUpdate(dao); inherit = dao.getContextInheritance(); assertEquals(serverTagMinigamesParents, inherit.getParents(serverMinigames)); assertEquals(worldNetherParents, inherit.getParents(worldNether)); } } @Test public void testRankLadder() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { final SubjectRef member = dao.getOrCreateSubjectRef("group", "member"), vip = dao.getOrCreateSubjectRef("group", "vip"), potato = dao.getOrCreateSubjectRef("group", "potato"), guest = dao.getOrCreateSubjectRef("group", "guest"), novice = dao.getOrCreateSubjectRef("group", "novice"); assertFalse(dao.hasEntriesForRankLadder("uncreated")); RankLadder uncreated = dao.getRankLadder("uncreated"); assertTrue(uncreated.getRanks().isEmpty()); dao.setRankLadder("test1", dao.getRankLadder("test1").addRank(guest).addRank(novice).addRank(member).addRank(vip)); RankLadder testLadder = dao.getRankLadder("test1"); assertEquals(ImmutableList.of(guest, novice, member, vip), testLadder.getRanks()); dao.setRankLadder("test1", dao.getRankLadder("another").addRank(potato)); testLadder = dao.getRankLadder("test1"); assertEquals(ImmutableList.of(potato), testLadder.getRanks()); assertEquals(ImmutableSet.of("test1"), dao.getAllRankLadderNames()); dao.setRankLadder("test1", null); testLadder = dao.getRankLadder("test1"); assertEquals(ImmutableSet.of(), dao.getAllRankLadderNames()); assertTrue(testLadder.getRanks().isEmpty()); } } @Test public void testInitializeTables() throws SQLException { try (SqlDao dao = sqlStore.getDao()) { dao.initializeTables(); // Because tables are already initialized, this should do nothing } } }