diff --git a/pom.xml b/pom.xml index 92a7453..115b7af 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 eu.lmc.tools applyalter - 4.9 + 5.0 applyalter @@ -23,70 +23,39 @@ commons-cli commons-cli - 1.2 + 1.5.0 commons-io commons-io - 2.0 + 2.11.0 - commons-lang - commons-lang - 2.6 + org.apache.commons + commons-lang3 + 3.12.0 - com.google.collections - google-collections - 1.0 - - - net.sf.opencsv + com.opencsv opencsv - 1.8 + 5.6 com.thoughtworks.xstream xstream - 1.3 - - - - - log4j - log4j - 1.2.15 - true - - - com.sun.jdmk - jmxtools - - - javax.mail - mail - - - javax.jms - jms - - - com.sun.jmx - jmxri - - + 1.4.19 - org.testng - testng - 5.14.9 + org.junit.jupiter + junit-jupiter + 5.9.0 test org.mockito - mockito-all - 1.9.0 + mockito-core + 4.7.0 test @@ -114,7 +83,7 @@ org.postgresql postgresql - 42.2.5 + 42.4.2 runtime @@ -141,7 +110,7 @@ jdeb org.vafer - 1.4 + 1.10 package @@ -182,16 +151,16 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.0 + 3.10.1 - 8 - 8 + 17 + 17 org.apache.maven.plugins maven-shade-plugin - 2.4 + 3.3.0 false diff --git a/src/main/java/ch/ips/g2/applyalter/ApplyAlter.java b/src/main/java/ch/ips/g2/applyalter/ApplyAlter.java index 45f3617..3b7ee4c 100644 --- a/src/main/java/ch/ips/g2/applyalter/ApplyAlter.java +++ b/src/main/java/ch/ips/g2/applyalter/ApplyAlter.java @@ -2,8 +2,6 @@ import ch.ips.g2.applyalter.logreport.ReportedResult; import ch.ips.g2.applyalter.logreport.StructuredLog; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStreamException; import org.apache.commons.cli.BasicParser; @@ -38,6 +36,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -155,7 +154,7 @@ public class ApplyAlter { protected XStream xstream = new XStream(); protected String username; - protected Multimap unapplied = ArrayListMultimap.create(); + protected Map> unapplied = new LinkedHashMap<>(); private boolean logTableUsed; private String environment; private boolean unknownInstancesIgnored = false; @@ -535,7 +534,9 @@ private void applySingleAlter(final Alter a, ApplyAlterExceptions aae) { if (RunMode.LOOK.equals(getRunMode())) { runContext.report(MAIN, "Alter %s seems unapplied", a.getId()); - unapplied.put(d.getId(), a.getId()); + final List data = unapplied.getOrDefault(d.getId(), new ArrayList<>()); + data.add(a.getId()); + unapplied.putIfAbsent(d.getId(), data); continue; } d.markConnectionUsed(runContext); @@ -784,7 +785,7 @@ public Set getApplyAlterLog(DbInstance d) { * @return concatenated list ready to print */ public String getUnappliedAlters() { - Multimap un = ArrayListMultimap.create(unapplied); + final Map> un = new LinkedHashMap<>(unapplied); StringBuilder s = new StringBuilder(); for (DbInstance d : db.getEntries()) { Collection c = un.get(d.getId()); diff --git a/src/main/java/ch/ips/g2/applyalter/CSV.java b/src/main/java/ch/ips/g2/applyalter/CSV.java index ea09b3c..eb141e3 100644 --- a/src/main/java/ch/ips/g2/applyalter/CSV.java +++ b/src/main/java/ch/ips/g2/applyalter/CSV.java @@ -1,13 +1,13 @@ package ch.ips.g2.applyalter; -import au.com.bytecode.opencsv.CSVReader; +import com.opencsv.CSVReader; +import com.opencsv.exceptions.CsvValidationException; import com.thoughtworks.xstream.annotations.XStreamAlias; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.ParameterMetaData; @@ -58,8 +58,8 @@ public CSV() { * Prepared statement parameters meta info. */ private static class ParamMeta { - private int typeId; - private String name; + private final int typeId; + private final String name; ;; ParamMeta(int typeId, String name) { @@ -93,7 +93,7 @@ public void execute(DbInstance dbConn, RunContext ctx, Map dataf throw new ApplyAlterException(String.format("missing top-level element: %s", getFile())); } - CSVReader rdr = new CSVReader(new InputStreamReader(new ByteArrayInputStream(rawFile), Charset.forName("UTF-8"))); + CSVReader rdr = new CSVReader(new InputStreamReader(new ByteArrayInputStream(rawFile), StandardCharsets.UTF_8)); PreparedStatement st = null; try { @@ -144,7 +144,7 @@ public void execute(DbInstance dbConn, RunContext ctx, Map dataf ctx.report(ReportLevel.STATEMENT_STEP, "statement executed %d times, changed rows: %d%n", execCnt, rows); rdr.close(); - } catch (IOException e) { + } catch (IOException | CsvValidationException e) { throw new ApplyAlterException("error reading CSV file " + getFile(), e); } finally { DbUtils.close(st); diff --git a/src/main/java/ch/ips/g2/applyalter/PgInstance.java b/src/main/java/ch/ips/g2/applyalter/PgInstance.java index b040c16..2bf06a0 100644 --- a/src/main/java/ch/ips/g2/applyalter/PgInstance.java +++ b/src/main/java/ch/ips/g2/applyalter/PgInstance.java @@ -1,6 +1,5 @@ package ch.ips.g2.applyalter; -import com.google.common.annotations.VisibleForTesting; import com.thoughtworks.xstream.annotations.XStreamAlias; import org.apache.commons.io.IOUtils; @@ -124,7 +123,7 @@ public String getPkgLogTable() { * matching line and if found, set password via {@link #setPass(String)} * @param runContext context (used by logging) */ - @VisibleForTesting void loadPgpass(RunContext runContext, InputStream pgpassInputStream) { + void loadPgpass(RunContext runContext, InputStream pgpassInputStream) { if (pgpassInputStream == null) return; //load whole file at once diff --git a/src/main/java/ch/ips/g2/applyalter/PkgLogTableHandler.java b/src/main/java/ch/ips/g2/applyalter/PkgLogTableHandler.java index a22dd68..5d454c0 100644 --- a/src/main/java/ch/ips/g2/applyalter/PkgLogTableHandler.java +++ b/src/main/java/ch/ips/g2/applyalter/PkgLogTableHandler.java @@ -5,7 +5,7 @@ import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.lang3.time.DateFormatUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -14,6 +14,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -136,7 +137,7 @@ public void queryAndWrite(@Nonnull String outputFile, @Nullable String hash) { Writer wr = null; try { final OutputStream os = stdout ? System.out : new FileOutputStream(outputFile); - wr = new OutputStreamWriter(os, "UTF-8"); + wr = new OutputStreamWriter(os, StandardCharsets.UTF_8); XStream xstream = new XStream(); xstream.processAnnotations(QueryResult.class); xstream.marshal(new QueryResult(result), new PrettyPrintWriter(wr)); @@ -179,7 +180,7 @@ public static class Record { public Record(String hash, String username, Timestamp at) { this.hash = hash; this.username = username; - this.at = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(at); + this.at = DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(at); } } diff --git a/src/main/java/ch/ips/g2/applyalter/logreport/XmlLoggingRunContext.java b/src/main/java/ch/ips/g2/applyalter/logreport/XmlLoggingRunContext.java index 2b0e3b4..483af6d 100644 --- a/src/main/java/ch/ips/g2/applyalter/logreport/XmlLoggingRunContext.java +++ b/src/main/java/ch/ips/g2/applyalter/logreport/XmlLoggingRunContext.java @@ -2,8 +2,8 @@ import ch.ips.g2.applyalter.ReportLevel; import ch.ips.g2.applyalter.RunContext; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.commons.lang3.time.DateFormatUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -19,10 +19,7 @@ import javax.xml.transform.stream.StreamResult; import java.io.IOException; import java.io.OutputStream; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.TimeZone; /** * Collect logs into json. @@ -42,7 +39,7 @@ public class XmlLoggingRunContext extends RunContext.WrapperRunContext { * Format date and time. */ protected String formatTime(Date time) { - return DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(time); + return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(time); } @@ -138,7 +135,7 @@ public void report(ReportLevel level, Exception e, String format, Object... args final Element msg = createMessageElement(format, args); if (e != null) { Element stacktrace = document.createElement("stacktrace"); - stacktrace.setTextContent(ExceptionUtils.getFullStackTrace(e)); + stacktrace.setTextContent(ExceptionUtils.getStackTrace(e)); msg.appendChild(stacktrace); } } diff --git a/src/test/java/ch/ips/g2/applyalter/BytesToHexTest.java b/src/test/java/ch/ips/g2/applyalter/BytesToHexTest.java index d1668a4..cc88981 100644 --- a/src/test/java/ch/ips/g2/applyalter/BytesToHexTest.java +++ b/src/test/java/ch/ips/g2/applyalter/BytesToHexTest.java @@ -1,34 +1,32 @@ package ch.ips.g2.applyalter; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import static ch.ips.g2.applyalter.AlterLoader.bytes2hex; +import static org.junit.jupiter.api.Assertions.assertEquals; /** + * */ -@Test -public class BytesToHexTest -{ - - public void testEmpty() - { - Assert.assertEquals( bytes2hex( new byte[0] ), "" ); - } - - public void testSingleByte() - { - for ( int i = 0; i < 256; i++ ) - Assert.assertEquals( bytes2hex( new byte[]{(byte) i} ), String.format( "%02X", i ) ); - } - - public void testBytes() - { - byte[] b1 = new byte[]{ - 15, 0x12, 0x34, 0x56, 0x78, (byte) 0x9a, (byte) 0xbc, 0xd, (byte) 0xef - }; - Assert.assertEquals( bytes2hex( b1 ), "0F123456789ABC0DEF" ); - } - - +public class BytesToHexTest { + + @Test + public void testEmpty() { + assertEquals("", bytes2hex(new byte[0])); + } + + @Test + public void testSingleByte() { + for (int i = 0; i < 256; i++) { + assertEquals(String.format("%02X", i), bytes2hex(new byte[]{(byte) i})); + } + } + + @Test + public void testBytes() { + byte[] b1 = new byte[]{ + 15, 0x12, 0x34, 0x56, 0x78, (byte) 0x9a, (byte) 0xbc, 0xd, (byte) 0xef + }; + assertEquals("0F123456789ABC0DEF", bytes2hex(b1)); + } } diff --git a/src/test/java/ch/ips/g2/applyalter/DbConfigFileTest.java b/src/test/java/ch/ips/g2/applyalter/DbConfigFileTest.java index 91980b0..7d406f4 100644 --- a/src/test/java/ch/ips/g2/applyalter/DbConfigFileTest.java +++ b/src/test/java/ch/ips/g2/applyalter/DbConfigFileTest.java @@ -1,11 +1,12 @@ package ch.ips.g2.applyalter; import com.thoughtworks.xstream.XStream; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class DbConfigFileTest { @Test @@ -29,6 +30,6 @@ public void generateConfigXmlTest() { System.out.println(xml); - Assert.assertTrue(xml.contains(""), "Final xml must contain element param with attribute name= roleRW"); + assertTrue(xml.contains(""), "Final xml must contain element param with attribute name= roleRW"); } } diff --git a/src/test/java/ch/ips/g2/applyalter/PgInstanceTest.java b/src/test/java/ch/ips/g2/applyalter/PgInstanceTest.java index 3617730..5b9d2cb 100644 --- a/src/test/java/ch/ips/g2/applyalter/PgInstanceTest.java +++ b/src/test/java/ch/ips/g2/applyalter/PgInstanceTest.java @@ -1,43 +1,47 @@ package ch.ips.g2.applyalter; +import org.junit.jupiter.api.Test; + import java.io.ByteArrayInputStream; -import org.testng.annotations.Test; +import java.nio.charset.StandardCharsets; -import static org.mockito.Mockito.*; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; -@Test public class PgInstanceTest { - // hostname:port:database:username:password - public void loadPgPassResolvePassForName() throws Exception { - PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", "dbadmin", null); - String pgpass = "*:*:*:*:secret"; - RunContext ctx = mock(RunContext.class); - pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes("UTF-8"))); - - assertEquals(pg.getUser(), "dbadmin"); - assertEquals(pg.getPass(), "secret"); - } - - public void loadPgPassResolvePassForMatchingName() throws Exception { - PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", "dbadmin", null); - String pgpass = "*:*:*:dbuser:weak\n" + - "*:*:*:dbadmin:secret"; - RunContext ctx = mock(RunContext.class); - pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes("UTF-8"))); - - assertEquals(pg.getUser(), "dbadmin"); - assertEquals(pg.getPass(), "secret"); - } - - public void loadPgPassResolveUserPass() throws Exception { - PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", null, null); - String pgpass = "*:*:*:dbadmin:secret"; - RunContext ctx = mock(RunContext.class); - pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes("UTF-8"))); - - assertEquals(pg.getUser(), "dbadmin"); - assertEquals(pg.getPass(), "secret"); - } + // hostname:port:database:username:password + @Test + public void loadPgPassResolvePassForName() throws Exception { + PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", "dbadmin", null); + String pgpass = "*:*:*:*:secret"; + RunContext ctx = mock(RunContext.class); + pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes(StandardCharsets.UTF_8))); + + assertEquals("dbadmin", pg.getUser()); + assertEquals("secret", pg.getPass()); + } + + @Test + public void loadPgPassResolvePassForMatchingName() throws Exception { + PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", "dbadmin", null); + String pgpass = "*:*:*:dbuser:weak\n" + + "*:*:*:dbadmin:secret"; + RunContext ctx = mock(RunContext.class); + pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes(StandardCharsets.UTF_8))); + + assertEquals("dbadmin", pg.getUser()); + assertEquals("secret", pg.getPass()); + } + + @Test + public void loadPgPassResolveUserPass() throws Exception { + PgInstance pg = new PgInstance("id", "type", "localhost", 5432, "main", null, null); + String pgpass = "*:*:*:dbadmin:secret"; + RunContext ctx = mock(RunContext.class); + pg.loadPgpass(ctx, new ByteArrayInputStream(pgpass.getBytes(StandardCharsets.UTF_8))); + + assertEquals("dbadmin", pg.getUser()); + assertEquals("secret", pg.getPass()); + } } diff --git a/src/test/java/ch/ips/g2/applyalter/ReplaceInputStreamTest.java b/src/test/java/ch/ips/g2/applyalter/ReplaceInputStreamTest.java index fe3cfba..445f1cc 100644 --- a/src/test/java/ch/ips/g2/applyalter/ReplaceInputStreamTest.java +++ b/src/test/java/ch/ips/g2/applyalter/ReplaceInputStreamTest.java @@ -1,26 +1,34 @@ package ch.ips.g2.applyalter; -import com.google.common.collect.ImmutableMap; import org.apache.commons.io.IOUtils; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class ReplaceInputStreamTest { - @Test(dataProvider = "provider") + // @Test(dataProvider = "provider") + @ParameterizedTest + @MethodSource("provider") public void testReplace(String input, Map params, String expOutput) throws IOException { - Assert.assertEquals(readAsInputStream(input, params), expOutput); + assertEquals(expOutput, readAsInputStream(input, params)); } - @Test(expectedExceptions = IllegalStateException.class) - public void testParamDoesNotExists() throws IOException { - readAsInputStream("Hello {{param}} world {{missingParam}}", ImmutableMap.of("param", "first")); + @Test + public void testParamDoesNotExists() { + Assertions.assertThrows(IllegalStateException.class, () -> + readAsInputStream("Hello {{param}} world {{missingParam}}", Map.of("param", "first")) + ); } private String readAsInputStream(final String input, final Map params) throws IOException { @@ -34,57 +42,55 @@ private String readAsInputStream(final String input, final Map p return IOUtils.toString(ris, charsetName); } - @DataProvider - private Object[][] provider() { - return new Object[][]{ - new Object[]{ + private static Stream provider() { + return Stream.of( + Arguments.of( "First test", - ImmutableMap.of(), + Map.of(), "First test" - }, - new Object[]{ + ), + Arguments.of( "First test", - ImmutableMap.of("db", "test"), + Map.of("db", "test"), "First test" - }, - new Object[]{ + ), + Arguments.of( "First {{}} test", - ImmutableMap.of("db", "test"), + Map.of("db", "test"), "First {{}} test" - }, + ), - new Object[]{ + Arguments.of( "First {{db}} test", - ImmutableMap.of("db", "brand0"), + Map.of("db", "brand0"), "First brand0 test" - }, - new Object[]{ + ), + Arguments.of( "First {{db}} test\nnext{{db}} line", - ImmutableMap.of("db", "brand0"), + Map.of("db", "brand0"), "First brand0 test\nnextbrand0 line" - }, - new Object[]{ + ), + Arguments.of( "Hello {{a}} world {{b}} next {{a}} word", - ImmutableMap.of("a", "first", "b", "second"), + Map.of("a", "first", "b", "second"), "Hello first world second next first word" - }, - new Object[]{ + ), + Arguments.of( "Second {{a b}} \nworld {{b\n}} next {{a}} word", - ImmutableMap.of("a", "first"), + Map.of("a", "first"), "Second {{a b}} \nworld {{b\n}} next first word" - }, - new Object[]{ + ), + Arguments.of( "Hello \n{{a-b_c}} world\nand {{def}} next \n xxx {{a-b_c}} word", - ImmutableMap.of("a-b_c", "first", "def", "second"), + Map.of("a-b_c", "first", "def", "second"), "Hello \nfirst world\nand second next \n xxx first word" - }, - new Object[]{ + ), + Arguments.of( "Hello {{a}} world {{b}}", - ImmutableMap.of("a", "{{b}}", "b", "{{a}}"), + Map.of("a", "{{b}}", "b", "{{a}}"), "Hello {{b}} world {{a}}" - } - - }; + ) + ); } } \ No newline at end of file