From 74f3be4b771161c18216986ba7de078aea01b117 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Wed, 8 Jul 2015 14:06:36 +0200 Subject: [PATCH 1/8] Moved back from Java 8 to Java 6 for Android --- pom.xml | 2 +- src/main/java/com/mapcode/DataAccess.java | 40 ++-- src/main/java/com/mapcode/Encoder.java | 2 +- src/main/java/com/mapcode/Mapcode.java | 15 +- src/main/java/com/mapcode/Range.java | 4 +- src/main/java/com/mapcode/SubArea.java | 34 ++-- src/main/java/com/mapcode/Territory.java | 12 +- src/site/apt/ReleaseNotes.apt.vm | 3 + .../java/com/mapcode/EncodeDecodeTest.java | 89 +++++---- src/test/java/com/mapcode/MapcodeTest.java | 46 +++-- .../java/com/mapcode/ReferenceFileTest.java | 189 +++++++++--------- 11 files changed, 227 insertions(+), 209 deletions(-) diff --git a/pom.xml b/pom.xml index cb330a6..75c6e1d 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ UTF-8 UTF-8 - 1.8 + 1.6 2.3.1 3.0.0 diff --git a/src/main/java/com/mapcode/DataAccess.java b/src/main/java/com/mapcode/DataAccess.java index 83655e3..c5c94a6 100755 --- a/src/main/java/com/mapcode/DataAccess.java +++ b/src/main/java/com/mapcode/DataAccess.java @@ -42,23 +42,31 @@ class DataAccess { final int bufferSize = 100000; final byte[] readBuffer = new byte[bufferSize]; int total = 0; - try (final InputStream inputStream = DataAccess.class.getResourceAsStream(FILE_NAME)) { - try (final ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - int nrBytes = inputStream.read(readBuffer); - while (nrBytes >= 0) { - total += nrBytes; - outputStream.write(readBuffer, 0, nrBytes); - nrBytes = inputStream.read(readBuffer); - } - - // Copy stream as unsigned bytes (ints). - final byte[] bytes = outputStream.toByteArray(); - assert total == bytes.length; - FILE_DATA = new int[total]; - for (int i = 0; i < total; ++i) { - FILE_DATA[i] = (bytes[i] < 0) ? (bytes[i] + 256) : bytes[i]; - + try { + final InputStream inputStream = DataAccess.class.getResourceAsStream(FILE_NAME); + try { + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try { + int nrBytes = inputStream.read(readBuffer); + while (nrBytes >= 0) { + total += nrBytes; + outputStream.write(readBuffer, 0, nrBytes); + nrBytes = inputStream.read(readBuffer); + } + + // Copy stream as unsigned bytes (ints). + final byte[] bytes = outputStream.toByteArray(); + assert total == bytes.length; + FILE_DATA = new int[total]; + for (int i = 0; i < total; ++i) { + FILE_DATA[i] = (bytes[i] < 0) ? (bytes[i] + 256) : bytes[i]; + + } + } finally { + outputStream.close(); } + } finally { + inputStream.close(); } } catch (final IOException e) { throw new ExceptionInInitializerError("Cannot initialize static data structure from: " + diff --git a/src/main/java/com/mapcode/Encoder.java b/src/main/java/com/mapcode/Encoder.java index ecbe799..1f509b2 100755 --- a/src/main/java/com/mapcode/Encoder.java +++ b/src/main/java/com/mapcode/Encoder.java @@ -71,7 +71,7 @@ private static List encode(final double argLatDeg, final double argLonD final Point pointToEncode = Point.fromDeg(latDeg, lonDeg); final List areas = SubArea.getAreasForPoint(pointToEncode); - final List results = new ArrayList<>(); + final List results = new ArrayList(); int lastbasesubareaID = -1; diff --git a/src/main/java/com/mapcode/Mapcode.java b/src/main/java/com/mapcode/Mapcode.java index d0b9bd8..0271dc4 100644 --- a/src/main/java/com/mapcode/Mapcode.java +++ b/src/main/java/com/mapcode/Mapcode.java @@ -246,11 +246,11 @@ public Territory getTerritory() { * provided as statics to only compile these patterns once. */ @Nonnull - static final String REGEX_TERRITORY = "[\\p{Alpha}\\p{Digit}]{2,3}+([-_][\\p{Alpha}\\p{Digit}]{2,3}+)?"; + static final String REGEX_TERRITORY = "[\\p{L}\\p{N}]{2,3}+([-_][\\p{L}\\p{N}]{2,3}+)?"; @Nonnull - static final String REGEX_CODE_PART = "[\\p{Alpha}\\p{Digit}]{2,5}+"; + static final String REGEX_CODE_PART = "[\\p{L}\\p{N}]{2,5}+"; @Nonnull - static final String REGEX_CODE_PRECISION = "[-][\\p{Alpha}\\p{Digit}&&[^zZ]]{1,2}+"; + static final String REGEX_CODE_PRECISION = "[-][\\p{L}\\p{N}&&[^zZ]]{1,2}+"; /** * This patterns/regular expressions is used for checking mapcode format strings. @@ -261,14 +261,11 @@ public Territory getTerritory() { REGEX_CODE_PART + "[.]" + REGEX_CODE_PART + '(' + REGEX_CODE_PRECISION + ")?"; @Nonnull - static final Pattern PATTERN_MAPCODE = - Pattern.compile('^' + REGEX_MAPCODE + '$', Pattern.UNICODE_CHARACTER_CLASS); + static final Pattern PATTERN_MAPCODE = Pattern.compile('^' + REGEX_MAPCODE + '$'); @Nonnull - static final Pattern PATTERN_TERRITORY = - Pattern.compile('^' + REGEX_TERRITORY + ' ', Pattern.UNICODE_CHARACTER_CLASS); + static final Pattern PATTERN_TERRITORY = Pattern.compile('^' + REGEX_TERRITORY + ' '); @Nonnull - static final Pattern PATTERN_PRECISION = - Pattern.compile(REGEX_CODE_PRECISION + '$', Pattern.UNICODE_CHARACTER_CLASS); + static final Pattern PATTERN_PRECISION = Pattern.compile(REGEX_CODE_PRECISION + '$'); /** * This enum describes the types of available mapcodes (as returned by {@link #getPrecisionFormat(String)}. diff --git a/src/main/java/com/mapcode/Range.java b/src/main/java/com/mapcode/Range.java index ee23301..70c95b8 100644 --- a/src/main/java/com/mapcode/Range.java +++ b/src/main/java/com/mapcode/Range.java @@ -80,12 +80,12 @@ Range constrain(@Nonnull final Range constrainingRange) { return null; } - return new Range<>(newMin, newMax); + return new Range(newMin, newMax); } @Nullable ArrayList> constrain(@Nonnull final ArrayList> constrainingRanges) { - final ArrayList> resultRanges = new ArrayList<>(); + final ArrayList> resultRanges = new ArrayList>(); for (final Range range : constrainingRanges) { final Range constrainedRange = constrain(range); if (constrainedRange != null) { diff --git a/src/main/java/com/mapcode/SubArea.java b/src/main/java/com/mapcode/SubArea.java index 57b5c8d..9bf3153 100644 --- a/src/main/java/com/mapcode/SubArea.java +++ b/src/main/java/com/mapcode/SubArea.java @@ -36,12 +36,12 @@ class SubArea { private static final int SUB_AREAS_INITIAL_CAPACITY = 16250; - private static final List SUB_AREAS = new ArrayList<>(SUB_AREAS_INITIAL_CAPACITY); - private static final TreeMap> LON_MAP = new TreeMap<>(); - private static final TreeMap> LAT_MAP = new TreeMap<>(); + private static final List SUB_AREAS = new ArrayList(SUB_AREAS_INITIAL_CAPACITY); + private static final TreeMap> LON_MAP = new TreeMap>(); + private static final TreeMap> LAT_MAP = new TreeMap>(); - private static final Range LAT_BOUNDING_RANGE = new Range<>(Point.LAT_MICRODEG_MIN, Point.LAT_MICRODEG_MAX); - private static final Range LON_BOUNDING_RANGE = new Range<>(Point.LON_MICRODEG_MIN, Point.LON_MICRODEG_MAX); + private static final Range LAT_BOUNDING_RANGE = new Range(Point.LAT_MICRODEG_MIN, Point.LAT_MICRODEG_MAX); + private static final Range LON_BOUNDING_RANGE = new Range(Point.LON_MICRODEG_MIN, Point.LON_MICRODEG_MAX); static { LOG.info("SubArea: Initialize sub-areas for {} territories", Territory.values().length); @@ -115,7 +115,7 @@ static SubArea getArea(final int i) { @SuppressWarnings("unchecked") @Nonnull static List getAreasForPoint(@Nonnull final Point point) { - final ArrayList> areaLists = new ArrayList<>(); + final ArrayList> areaLists = new ArrayList>(); ArrayList list; list = LAT_MAP.get(point.getLatMicroDeg()); @@ -158,7 +158,7 @@ static List getAreasForPoint(@Nonnull final Point point) { areaLists.add(list); } - final ArrayList result = new ArrayList<>(); + final ArrayList result = new ArrayList(); list = areaLists.get(0); mainLoop: @@ -208,8 +208,8 @@ private SubArea(final int i, @Nonnull final Territory territory, @Nullable final minMaxSetup(i); parentTerritory = territory; subAreaID = i; - boundedLonRange = new ArrayList<>(); - boundedLatRange = new ArrayList<>(); + boundedLonRange = new ArrayList>(); + boundedLatRange = new ArrayList>(); // Mapcode areas are inclusive for the minimum bounds and exclusive for the maximum bounds // Trim max by 1, to address boundary cases. @@ -246,7 +246,7 @@ private SubArea(final int i, @Nonnull final Territory territory, @Nullable final @Nonnull private static ArrayList> normaliseRange( @Nonnull final Range range, @Nonnull final Range boundingRange) { - final ArrayList> ranges = new ArrayList<>(); + final ArrayList> ranges = new ArrayList>(); Range tempRange = range.constrain(boundingRange); if (tempRange != null) { @@ -255,7 +255,7 @@ private static ArrayList> normaliseRange( Range normalisingRange = range; while (normalisingRange.getMin() < boundingRange.getMin()) { - normalisingRange = new Range<>((normalisingRange.getMin() + boundingRange.getMax()) + normalisingRange = new Range((normalisingRange.getMin() + boundingRange.getMax()) - boundingRange.getMin(), (normalisingRange.getMax() + boundingRange.getMax()) - boundingRange.getMin()); tempRange = normalisingRange.constrain(boundingRange); @@ -266,7 +266,7 @@ private static ArrayList> normaliseRange( normalisingRange = range; while (normalisingRange.getMax() > boundingRange.getMax()) { - normalisingRange = new Range<>((normalisingRange.getMin() - boundingRange.getMax()) + normalisingRange = new Range((normalisingRange.getMin() - boundingRange.getMax()) + boundingRange.getMin(), (normalisingRange.getMax() - boundingRange.getMax()) + boundingRange.getMin()); tempRange = normalisingRange.constrain(boundingRange); @@ -293,8 +293,8 @@ boolean containsPoint(@Nonnull final Point point) { @Nonnull SubArea extendBounds(final int xExtension, final int yExtension) { final SubArea result = new SubArea(); - result.latRange = new Range<>(this.getMinY() - yExtension, getMaxY() + yExtension); - result.lonRange = new Range<>(this.getMinX() - xExtension, getMaxX() + xExtension); + result.latRange = new Range(this.getMinY() - yExtension, getMaxY() + yExtension); + result.lonRange = new Range(this.getMinX() - xExtension, getMaxX() + xExtension); return result; } @@ -327,11 +327,11 @@ private void minMaxSetup(final int arg) { i += 4; final int maxY = DataAccess.asLong(i); - latRange = new Range<>(minY, maxY); - lonRange = new Range<>(minX, maxX); + latRange = new Range(minY, maxY); + lonRange = new Range(minX, maxX); } private static Range trimRange(final Range range) { - return new Range<>(range.getMin(), range.getMax() - 1); + return new Range(range.getMin(), range.getMax() - 1); } } diff --git a/src/main/java/com/mapcode/Territory.java b/src/main/java/com/mapcode/Territory.java index ca4a1a2..cd1c58c 100755 --- a/src/main/java/com/mapcode/Territory.java +++ b/src/main/java/com/mapcode/Territory.java @@ -822,13 +822,13 @@ private Territory( */ static { final String errorPrefix = "Initializing error: "; - codeList = new ArrayList<>(); - nameMap = new HashMap<>(); - parentList = new ArrayList<>(); + codeList = new ArrayList(); + nameMap = new HashMap>(); + parentList = new ArrayList(); int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - final Set territoryCodes = new HashSet<>(); - final Set aliasesSet = new HashSet<>(); + final Set territoryCodes = new HashSet(); + final Set aliasesSet = new HashSet(); for (final Territory territory : Territory.values()) { final int territoryNumber = territory.getNumber(); @@ -986,7 +986,7 @@ private static void addName(@Nonnull final String name, @Nonnull final Territory } territories.add(territory); } else { - final ArrayList arrayList = new ArrayList<>(); + final ArrayList arrayList = new ArrayList(); arrayList.add(territory); nameMap.put(name, arrayList); } diff --git a/src/site/apt/ReleaseNotes.apt.vm b/src/site/apt/ReleaseNotes.apt.vm index 87b3f1f..c56ce60 100755 --- a/src/site/apt/ReleaseNotes.apt.vm +++ b/src/site/apt/ReleaseNotes.apt.vm @@ -11,6 +11,9 @@ Release Notes (Version ${project.version}) * 2.0.1 + * Reverted Java JDK level to 1.6 (Java 6) from 1.8 (Java 8), so the library can be used on + Android platforms operating at Java 6 as well. + * Use multi-threading for long running test to speed them up (uses all CPU cores now). * 2.0.0 diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index 6efdd35..94da9ec 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -86,53 +86,56 @@ private static void doEncodeDecode(final long seed) throws InterruptedException // Walk through the list in reverse order to get International first. for (final Territory territory : Territory.values()) { - executor.execute(() -> { - try { - final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); - for (final Mapcode mapcode : resultsLimited) { - - // Check if the territory matches. - assertEquals(territory, mapcode.getTerritory()); - - // Check max distance. - final String codePrecision0 = mapcode.getCode(0); - final String codePrecision1 = mapcode.getCode(1); - final String codePrecision2 = mapcode.getCode(2); - - final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); - final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); - final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); - - final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); - final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); - final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); - - if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); - errors.getAndIncrement(); - } - if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); - errors.getAndIncrement(); - } - if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); - errors.getAndIncrement(); - } + executor.execute(new Runnable() { + @Override + public void run() { + try { + final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); + for (final Mapcode mapcode : resultsLimited) { + + // Check if the territory matches. + assertEquals(territory, mapcode.getTerritory()); + + // Check max distance. + final String codePrecision0 = mapcode.getCode(0); + final String codePrecision1 = mapcode.getCode(1); + final String codePrecision2 = mapcode.getCode(2); + + final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); + final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); + final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); + + final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); + final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); + final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); + + if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); + errors.getAndIncrement(); + } + if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); + errors.getAndIncrement(); + } + if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); + errors.getAndIncrement(); + } - // Check conversion from/to alphabets. - for (final Alphabet alphabet : Alphabet.values()) { - final String mapcodeAlphabet = mapcode.getCode(alphabet); - final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); - if (!codePrecision0.equals(mapcodeAscii)) { - LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + - ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); + // Check conversion from/to alphabets. + for (final Alphabet alphabet : Alphabet.values()) { + final String mapcodeAlphabet = mapcode.getCode(alphabet); + final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); + if (!codePrecision0.equals(mapcodeAscii)) { + LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + + ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); + } } } + } catch (final Exception e) { + LOG.error("encodeDecodeTest: Unexpected exception: ", e); + errors.getAndIncrement(); } - } catch (final Exception e) { - LOG.error("encodeDecodeTest: Unexpected exception: ", e); - errors.getAndIncrement(); } }); } diff --git a/src/test/java/com/mapcode/MapcodeTest.java b/src/test/java/com/mapcode/MapcodeTest.java index 36f8ff4..1f7d11a 100644 --- a/src/test/java/com/mapcode/MapcodeTest.java +++ b/src/test/java/com/mapcode/MapcodeTest.java @@ -30,29 +30,29 @@ public class MapcodeTest { public void checkValidPrecisionFormats() { LOG.info("checkValidPrecisionFormats"); - assertTrue(Mapcode.isValidPrecisionFormat("A1.B1")); - assertTrue(Mapcode.isValidPrecisionFormat("a1.B1")); - assertTrue(Mapcode.isValidPrecisionFormat("00.01")); - assertTrue(Mapcode.isValidPrecisionFormat("AAA.01")); - assertTrue(Mapcode.isValidPrecisionFormat("AAA.BBB")); - assertTrue(Mapcode.isValidPrecisionFormat("AAAA.BBB")); - assertTrue(Mapcode.isValidPrecisionFormat("AAAA.BBBB")); - assertTrue(Mapcode.isValidPrecisionFormat("AAAAA.BBBB")); - assertTrue(Mapcode.isValidPrecisionFormat("AAAAA.BBBBB")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-0")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-01")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-A")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-AA")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-Y")); - assertTrue(Mapcode.isValidPrecisionFormat("AA.AA-1Y")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("A1.B1")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("a1.B1")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("00.01")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAA.01")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAA.BBB")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAAA.BBB")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAAA.BBBB")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAAAA.BBBB")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AAAAA.BBBBB")); + assertEquals(PrecisionFormat.PRECISION_1, Mapcode.getPrecisionFormat("AA.AA-0")); + assertEquals(PrecisionFormat.PRECISION_2, Mapcode.getPrecisionFormat("AA.AA-01")); + assertEquals(PrecisionFormat.PRECISION_1, Mapcode.getPrecisionFormat("AA.AA-A")); + assertEquals(PrecisionFormat.PRECISION_2, Mapcode.getPrecisionFormat("AA.AA-AA")); + assertEquals(PrecisionFormat.PRECISION_1, Mapcode.getPrecisionFormat("AA.AA-Y")); + assertEquals(PrecisionFormat.PRECISION_2, Mapcode.getPrecisionFormat("AA.AA-1Y")); // Mapcode may contain correctly formatted (possible incorrect) territory code. - assertTrue(Mapcode.isValidPrecisionFormat("NLD XX.XX")); - assertTrue(Mapcode.isValidPrecisionFormat("USA-NLD XX.XX")); - assertTrue(Mapcode.isValidPrecisionFormat("IN XX.XX")); - assertTrue(Mapcode.isValidPrecisionFormat("US-IN XX.XX")); - assertTrue(Mapcode.isValidPrecisionFormat("US_IN XX.XX")); - assertTrue(Mapcode.isValidPrecisionFormat("RU-IN XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("NLD XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("USA-NLD XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("IN XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("US-IN XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("US_IN XX.XX")); + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("RU-IN XX.XX")); } @Test @@ -100,6 +100,10 @@ public void checkPrecisionFormat1() { assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("AA.BB")); assertEquals(PrecisionFormat.PRECISION_1, Mapcode.getPrecisionFormat("AA.BB-1")); assertEquals(PrecisionFormat.PRECISION_2, Mapcode.getPrecisionFormat("AA.BB-12")); + + assertEquals(PrecisionFormat.PRECISION_0, Mapcode.getPrecisionFormat("\u0e9a\u0e97\u0e84 \u0eab\u0ea7\u0e84.\u0ea73\u0eaa")); + assertEquals(PrecisionFormat.PRECISION_1, Mapcode.getPrecisionFormat("\u0f40\u0f64\u0f4c \u0f535\u0f41\u0f42.5\u0f629-\u0f40")); + assertEquals(PrecisionFormat.PRECISION_2, Mapcode.getPrecisionFormat("\u039d\u039b\u0394 \u03a7\u03a6\u0394.\u03a63\u03a9-\u039e7")); } @Test(expected = UnknownPrecisionFormatException.class) diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index 0bcd538..94028d6 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -139,114 +139,117 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti ++i; - executor.execute(() -> { - // Encode lat/lon to series of mapcodes and check the resulting mapcodes. - final List results = MapcodeCodec.encode( - reference.point.getLatDeg(), reference.point.getLonDeg()); - - // Check the number of mapcodes. - if (results.isEmpty()) { - LOG.error("checkFile: encode fails, no results found for reference={}", reference); - errors.incrementAndGet(); - } - - // Check encodeToInternational. - final Mapcode resultInternational = MapcodeCodec.encodeToInternational( - reference.point.getLatDeg(), reference.point.getLonDeg()); - final Mapcode expectedInternational = results.get(results.size() - 1); - if (!resultInternational.equals(expectedInternational)) { - LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", - expectedInternational, resultInternational, reference); - errors.incrementAndGet(); - } - - // Check the size of the results. - if (reference.mapcodes.size() != results.size()) { - final ArrayList resultsConverted = new ArrayList<>(results.size()); - for (final Mapcode mapcode : results) { - resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); + executor.execute(new Runnable() { + @Override + public void run() { + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. + final List results = MapcodeCodec.encode( + reference.point.getLatDeg(), reference.point.getLonDeg()); + + // Check the number of mapcodes. + if (results.isEmpty()) { + LOG.error("checkFile: encode fails, no results found for reference={}", reference); + errors.incrementAndGet(); } - LOG.error("checkFile: Incorrect number of results:" + - "\n lat/lon = {}" + - "\n expected = #{}: {} results," + - "\n actual = #{}: {} results\n", - reference.point, - reference.mapcodes.size(), - GSON.toJson(reference.mapcodes), - results.size(), - GSON.toJson(resultsConverted)); - errors.incrementAndGet(); - } - // For every mapcode in the result set, check if it is contained in the reference set. - int precision = 0; - for (final Mapcode result : results) { - boolean found = false; - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; - } - } + // Check encodeToInternational. + final Mapcode resultInternational = MapcodeCodec.encodeToInternational( + reference.point.getLatDeg(), reference.point.getLonDeg()); + final Mapcode expectedInternational = results.get(results.size() - 1); + if (!resultInternational.equals(expectedInternational)) { + LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", + expectedInternational, resultInternational, reference); + errors.incrementAndGet(); } - if (!found) { - // This does not fail the test, but rather produces an ERROR in the log file. - // It indicates a discrepancy in the C and Java implementations. - LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + - "ref={}\n" + "new={}", - result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + // Check the size of the results. + if (reference.mapcodes.size() != results.size()) { + final ArrayList resultsConverted = new ArrayList(results.size()); + for (final Mapcode mapcode : results) { + resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); + } + LOG.error("checkFile: Incorrect number of results:" + + "\n lat/lon = {}" + + "\n expected = #{}: {} results," + + "\n actual = #{}: {} results\n", + reference.point, + reference.mapcodes.size(), + GSON.toJson(reference.mapcodes), + results.size(), + GSON.toJson(resultsConverted)); errors.incrementAndGet(); } - } - // For every Mapcode in the reference set, check if it is contained in the result set. - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - boolean found = false; + // For every mapcode in the result set, check if it is contained in the reference set. + int precision = 0; for (final Mapcode result : results) { - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; + boolean found = false; + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } } } + if (!found) { + + // This does not fail the test, but rather produces an ERROR in the log file. + // It indicates a discrepancy in the C and Java implementations. + LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + + "ref={}\n" + "new={}", + result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + errors.incrementAndGet(); + } } - if (!found) { - LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + - "ref={}", - referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, - GSON.toJson(reference)); - errors.incrementAndGet(); - } - } - // Check distance of decoded point to reference point. - for (final MapcodeRec mapcodeRec : reference.mapcodes) { - //noinspection NestedTryStatement - try { - final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); - final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); - synchronized (deltaNm) { - deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + // For every Mapcode in the reference set, check if it is contained in the result set. + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + boolean found = false; + for (final Mapcode result : results) { + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } + } } + if (!found) { + LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + + "ref={}", + referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, + GSON.toJson(reference)); + errors.incrementAndGet(); + } + } - final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? - Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); - if (distanceNm > maxDeltaNm) { - LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + - "which is {} meters from the original point (max is {} meters).", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, - ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + // Check distance of decoded point to reference point. + for (final MapcodeRec mapcodeRec : reference.mapcodes) { + //noinspection NestedTryStatement + try { + final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); + final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); + synchronized (deltaNm) { + deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + } + + final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? + Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); + if (distanceNm > maxDeltaNm) { + LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + + "which is {} meters from the original point (max is {} meters).", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, + ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + errors.incrementAndGet(); + } + } catch (final UnknownMapcodeException unknownMapcodeException) { + LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point); errors.incrementAndGet(); } - } catch (final UnknownMapcodeException unknownMapcodeException) { - LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point); - errors.incrementAndGet(); } } }); @@ -308,7 +311,7 @@ private static ReferenceRec getNextReferenceRecord(@Nonnull final ChunkedFile ch assertTrue("Longitude must be in [-180, 180]", (-180 <= point.getLonDeg()) && (point.getLonDeg() <= 180)); // Read mapcodes: - final ArrayList mapcodeRecs = new ArrayList<>(); + final ArrayList mapcodeRecs = new ArrayList(); for (int i = 0; i < count; ++i) { final String line = chunkedFile.readNonEmptyLine(); assertTrue("Line should not be empty", !line.isEmpty()); From b14bcf87c3797bc2b6e78aff586c497170bc4640 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Wed, 8 Jul 2015 15:20:50 +0200 Subject: [PATCH 2/8] Allows use of territory names as well as codes --- src/main/java/com/mapcode/Territory.java | 29 ++++++++++++++++---- src/site/apt/ReleaseNotes.apt.vm | 2 ++ src/test/java/com/mapcode/TerritoryTest.java | 17 ++++++++---- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/mapcode/Territory.java b/src/main/java/com/mapcode/Territory.java index cd1c58c..17956ae 100755 --- a/src/main/java/com/mapcode/Territory.java +++ b/src/main/java/com/mapcode/Territory.java @@ -646,7 +646,7 @@ static Territory fromNumber(final int number) throws UnknownTerritoryException { } /** - * Get a territory from a mapcode territory abbreviation. Note that the provided abbreviation is NOT an + * Get a territory from a mapcode territory abbreviation (or a territory name). Note that the provided abbreviation is NOT an * ISO code: it's a mapcode prefix. As local mapcodes for subdivisions have been optimized to prefer to use 2-character * subdivisions codes in local codes, subdivisions are preferred over countries in this case. * @@ -658,7 +658,7 @@ static Territory fromNumber(final int number) throws UnknownTerritoryException { * * Brazilian mapcodes, on the other hand, would be specified as "BRA BDHP.JK39-1D", using the ISO 3 letter code. * - * @param alphaCode Territory, alphanumeric code. + * @param alphaCode Territory name or alphanumeric code. * @return Territory. * @throws UnknownTerritoryException Thrown if incorrect numeric or alphanumeric code. */ @@ -828,7 +828,7 @@ private Territory( int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; final Set territoryCodes = new HashSet(); - final Set aliasesSet = new HashSet(); + final Set namesSet = new HashSet(); for (final Territory territory : Territory.values()) { final int territoryNumber = territory.getNumber(); @@ -849,14 +849,33 @@ private Territory( if ((territory.parentTerritory != null) && !parentList.contains(territory.parentTerritory)) { parentList.add(territory.parentTerritory); } + + // Add territory codes and alias codes. + if (namesSet.contains(territory.toString())) { + throw new ExceptionInInitializerError(errorPrefix + "non-unique territory: " + territory.toString()); + } + namesSet.add(territory.toString()); addNameWithParentVariants(territory.toString(), territory); for (final String alias : territory.aliases) { - if (aliasesSet.contains(alias)) { + if (namesSet.contains(alias)) { throw new ExceptionInInitializerError(errorPrefix + "non-unique alias: " + alias); } - aliasesSet.add(alias); + namesSet.add(alias); addNameWithParentVariants(alias, territory); } + + // Add territory fullnames and aliases as well. Skip special case: territory name == territory code (e.g. USA). + if (namesSet.contains(territory.fullName.toUpperCase()) && !territory.toString().equals(territory.fullName.toUpperCase())) { + throw new ExceptionInInitializerError(errorPrefix + "non-unique fullName: " + territory.fullName.toUpperCase()); + } + addNameWithParentVariants(territory.fullName.toUpperCase(), territory); + for (final String fullNameAlias : territory.fullNameAliases) { + if (namesSet.contains(fullNameAlias.toUpperCase())) { + throw new ExceptionInInitializerError(errorPrefix + "non-unique fullName alias: " + fullNameAlias); + } + namesSet.add(fullNameAlias.toUpperCase()); + addNameWithParentVariants(fullNameAlias.toUpperCase(), territory); + } min = Math.min(min, territory.number); max = Math.max(max, territory.number); } diff --git a/src/site/apt/ReleaseNotes.apt.vm b/src/site/apt/ReleaseNotes.apt.vm index c56ce60..cdcd4ed 100755 --- a/src/site/apt/ReleaseNotes.apt.vm +++ b/src/site/apt/ReleaseNotes.apt.vm @@ -16,6 +16,8 @@ Release Notes (Version ${project.version}) * Use multi-threading for long running test to speed them up (uses all CPU cores now). + * Added the ability to use a country name for <<>>. + * 2.0.0 * Fixes to the data rectangles (primarily intended for ISO proposal). diff --git a/src/test/java/com/mapcode/TerritoryTest.java b/src/test/java/com/mapcode/TerritoryTest.java index d3cafe9..102078e 100644 --- a/src/test/java/com/mapcode/TerritoryTest.java +++ b/src/test/java/com/mapcode/TerritoryTest.java @@ -34,6 +34,17 @@ public void emptyTerritoryCodeTest() throws Exception { Territory.fromString(""); } + @Test + public void checkFullName() throws Exception { + LOG.info("checkFullName"); + assertEquals(Territory.AAA, Territory.fromString("International")); + assertEquals(Territory.AAA, Territory.fromString("Worldwide")); + assertEquals(Territory.AAA, Territory.fromString("Earth")); + assertEquals(Territory.NLD, Territory.fromString("Netherlands")); + assertEquals(Territory.CN_XZ, Territory.fromString("Xizang")); + assertEquals(Territory.CN_XZ, Territory.fromString("Tibet")); + } + @Test public void checkDash() throws Exception { LOG.info("checkDash"); @@ -126,10 +137,4 @@ public void testFromStringError3() { LOG.info("testFromStringError3"); Territory.fromString("999"); } - - @Test(expected = IllegalArgumentException.class) - public void testFromStringError4() { - LOG.info("testFromStringError4"); - Territory.fromString("Netherlands"); - } } From 62323b43190ec7dd805cdd321214f5a0830cd4e8 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 13:39:04 +0200 Subject: [PATCH 3/8] Updated POM --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 75c6e1d..a3bc969 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ mapcode jar - 2.0.1-SNAPSHOT + 2.0.1 Mapcode Java Library From 0b1bb387ea1ed737fb6193b628d281790c4421d6 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 15:18:44 +0200 Subject: [PATCH 4/8] Change thread pooling for tests --- .../java/com/mapcode/EncodeDecodeTest.java | 131 +++++----- .../java/com/mapcode/ReferenceFileTest.java | 233 ++++++++++-------- 2 files changed, 200 insertions(+), 164 deletions(-) diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index 94da9ec..d1e7457 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -24,9 +24,7 @@ import java.util.List; import java.util.Random; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertEquals; @@ -39,9 +37,9 @@ public class EncodeDecodeTest { new GsonBuilder().serializeSpecialFloatingPointValues().create(); private static final int NUMBER_OF_POINTS = 5000; + private static final int NUMBER_OF_TASKS = NUMBER_OF_POINTS * Territory.values().length; private static final int LOG_LINE_EVERY = 500; - @Test public void encodeDecodeTestFixedSeed() throws Exception { final long seed = 1431977987367L; @@ -56,19 +54,22 @@ public void encodeDecodeTestRandomSeed() throws Exception { doEncodeDecode(seed); } + @SuppressWarnings("BusyWait") private static void doEncodeDecode(final long seed) throws InterruptedException { // Keep error count and create thread pool. final AtomicInteger errors = new AtomicInteger(0); + final AtomicInteger tasks = new AtomicInteger(0); + final int threads = Runtime.getRuntime().availableProcessors(); LOG.info("encodeDecodeTest: Starting {} threads...", threads); - final ExecutorService executor = Executors.newFixedThreadPool(threads); + final ExecutorService executor = new ThreadPoolExecutor( + threads, threads, // Fixed number of threads. + 0L, TimeUnit.MILLISECONDS, // No keep-alive. + new LinkedBlockingQueue(25000)); // Reasonable-size blocking queue. final Random randomGenerator = new Random(seed); for (int i = 0; i < NUMBER_OF_POINTS; i++) { - if ((i % LOG_LINE_EVERY) == 0) { - LOG.info("encodeDecodeTest: #{}/{}", i, NUMBER_OF_POINTS); - } // Encode location. final Point encode = Point.fromUniformlyDistributedRandomPoints(randomGenerator); @@ -86,62 +87,82 @@ private static void doEncodeDecode(final long seed) throws InterruptedException // Walk through the list in reverse order to get International first. for (final Territory territory : Territory.values()) { - executor.execute(new Runnable() { - @Override - public void run() { - try { - final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); - for (final Mapcode mapcode : resultsLimited) { - - // Check if the territory matches. - assertEquals(territory, mapcode.getTerritory()); - - // Check max distance. - final String codePrecision0 = mapcode.getCode(0); - final String codePrecision1 = mapcode.getCode(1); - final String codePrecision2 = mapcode.getCode(2); - - final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); - final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); - final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); - - final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); - final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); - final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); - - if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); - errors.getAndIncrement(); - } - if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); - errors.getAndIncrement(); - } - if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); - errors.getAndIncrement(); - } + while (true) { + try { + executor.execute(new Runnable() { + + @Override + public void run() { + try { + final int count = tasks.incrementAndGet(); + if ((count % LOG_LINE_EVERY) == 0) { + LOG.info("encodeDecodeTest: #{}/{}", count, NUMBER_OF_TASKS); + } - // Check conversion from/to alphabets. - for (final Alphabet alphabet : Alphabet.values()) { - final String mapcodeAlphabet = mapcode.getCode(alphabet); - final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); - if (!codePrecision0.equals(mapcodeAscii)) { - LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + - ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); + final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); + for (final Mapcode mapcode : resultsLimited) { + + // Check if the territory matches. + assertEquals(territory, mapcode.getTerritory()); + + // Check max distance. + final String codePrecision0 = mapcode.getCode(0); + final String codePrecision1 = mapcode.getCode(1); + final String codePrecision2 = mapcode.getCode(2); + + final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); + final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); + final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); + + final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); + final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); + final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); + + if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); + errors.getAndIncrement(); + } + if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); + errors.getAndIncrement(); + } + if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); + errors.getAndIncrement(); + } + + // Check conversion from/to alphabets. + for (final Alphabet alphabet : Alphabet.values()) { + final String mapcodeAlphabet = mapcode.getCode(alphabet); + final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); + if (!codePrecision0.equals(mapcodeAscii)) { + LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + + ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); + } + } } + } catch (final Exception e) { + LOG.error("encodeDecodeTest: Unexpected exception: ", e); + errors.getAndIncrement(); } } - } catch (final Exception e) { - LOG.error("encodeDecodeTest: Unexpected exception: ", e); - errors.getAndIncrement(); - } + }); + + // Break out of loop and process next value. + break; + + } catch (final RejectedExecutionException ignored) { + + // Perfectly fine; buffer is full. Just wait a bit and re-enter while loop. + LOG.info("encodeDecodeTest: buffer full, waiting, executed {} tasks so far", tasks); + Thread.sleep(1000); } - }); + } } } executor.shutdown(); executor.awaitTermination(60, TimeUnit.SECONDS); assertEquals("Found errors", 0, errors.get()); + LOG.info("encodeDecodeTest: executed {} tasks", tasks); } } diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index 94028d6..ed12476 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -26,9 +26,7 @@ import java.io.*; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -111,6 +109,7 @@ public void checkBoundariesReferenceRecordsPrecision2() throws Exception { checkFile(BOUNDARIES_REFERENCE_FILE_HP); } + @SuppressWarnings("BusyWait") private static void checkFile(@Nonnull final String baseFileName) throws Exception { // Reset error count. @@ -118,7 +117,10 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti final AtomicInteger errors = new AtomicInteger(0); final int threads = Runtime.getRuntime().availableProcessors(); LOG.info("checkFile: Starting {} threads...", threads); - final ExecutorService executor = Executors.newFixedThreadPool(threads); + final ExecutorService executor = new ThreadPoolExecutor( + threads, threads, // Fixed number of threads. + 0L, TimeUnit.MILLISECONDS, // No keep-alive. + new LinkedBlockingQueue(1000)); // Reasonable-size blocking queue. // Open data file. final ChunkedFile chunkedFile = new ChunkedFile(baseFileName); @@ -138,121 +140,134 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti } ++i; + while (true) { + try { + // Add task. This may throw an exception if the queue is full. Retry in that case. + executor.execute(new Runnable() { - executor.execute(new Runnable() { - @Override - public void run() { - // Encode lat/lon to series of mapcodes and check the resulting mapcodes. - final List results = MapcodeCodec.encode( - reference.point.getLatDeg(), reference.point.getLonDeg()); - - // Check the number of mapcodes. - if (results.isEmpty()) { - LOG.error("checkFile: encode fails, no results found for reference={}", reference); - errors.incrementAndGet(); - } - - // Check encodeToInternational. - final Mapcode resultInternational = MapcodeCodec.encodeToInternational( - reference.point.getLatDeg(), reference.point.getLonDeg()); - final Mapcode expectedInternational = results.get(results.size() - 1); - if (!resultInternational.equals(expectedInternational)) { - LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", - expectedInternational, resultInternational, reference); - errors.incrementAndGet(); - } - - // Check the size of the results. - if (reference.mapcodes.size() != results.size()) { - final ArrayList resultsConverted = new ArrayList(results.size()); - for (final Mapcode mapcode : results) { - resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); - } - LOG.error("checkFile: Incorrect number of results:" + - "\n lat/lon = {}" + - "\n expected = #{}: {} results," + - "\n actual = #{}: {} results\n", - reference.point, - reference.mapcodes.size(), - GSON.toJson(reference.mapcodes), - results.size(), - GSON.toJson(resultsConverted)); - errors.incrementAndGet(); - } - - // For every mapcode in the result set, check if it is contained in the reference set. - int precision = 0; - for (final Mapcode result : results) { - boolean found = false; - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; + @Override + public void run() { + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. + final List results = MapcodeCodec.encode( + reference.point.getLatDeg(), reference.point.getLonDeg()); + + // Check the number of mapcodes. + if (results.isEmpty()) { + LOG.error("checkFile: encode fails, no results found for reference={}", reference); + errors.incrementAndGet(); + } + + // Check encodeToInternational. + final Mapcode resultInternational = MapcodeCodec.encodeToInternational( + reference.point.getLatDeg(), reference.point.getLonDeg()); + final Mapcode expectedInternational = results.get(results.size() - 1); + if (!resultInternational.equals(expectedInternational)) { + LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", + expectedInternational, resultInternational, reference); + errors.incrementAndGet(); + } + + // Check the size of the results. + if (reference.mapcodes.size() != results.size()) { + final ArrayList resultsConverted = new ArrayList(results.size()); + for (final Mapcode mapcode : results) { + resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); } + LOG.error("checkFile: Incorrect number of results:" + + "\n lat/lon = {}" + + "\n expected = #{}: {} results," + + "\n actual = #{}: {} results\n", + reference.point, + reference.mapcodes.size(), + GSON.toJson(reference.mapcodes), + results.size(), + GSON.toJson(resultsConverted)); + errors.incrementAndGet(); } - } - if (!found) { - - // This does not fail the test, but rather produces an ERROR in the log file. - // It indicates a discrepancy in the C and Java implementations. - LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + - "ref={}\n" + "new={}", - result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); - errors.incrementAndGet(); - } - } - - // For every Mapcode in the reference set, check if it is contained in the result set. - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - boolean found = false; - for (final Mapcode result : results) { - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; + + // For every mapcode in the result set, check if it is contained in the reference set. + int precision = 0; + for (final Mapcode result : results) { + boolean found = false; + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } + } + } + if (!found) { + + // This does not fail the test, but rather produces an ERROR in the log file. + // It indicates a discrepancy in the C and Java implementations. + LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + + "ref={}\n" + "new={}", + result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + errors.incrementAndGet(); } } - } - if (!found) { - LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + - "ref={}", - referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, - GSON.toJson(reference)); - errors.incrementAndGet(); - } - } - - // Check distance of decoded point to reference point. - for (final MapcodeRec mapcodeRec : reference.mapcodes) { - //noinspection NestedTryStatement - try { - final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); - final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); - synchronized (deltaNm) { - deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + + // For every Mapcode in the reference set, check if it is contained in the result set. + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + boolean found = false; + for (final Mapcode result : results) { + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } + } + } + if (!found) { + LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + + "ref={}", + referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, + GSON.toJson(reference)); + errors.incrementAndGet(); + } } - final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? - Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); - if (distanceNm > maxDeltaNm) { - LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + - "which is {} meters from the original point (max is {} meters).", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, - ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); - errors.incrementAndGet(); + // Check distance of decoded point to reference point. + for (final MapcodeRec mapcodeRec : reference.mapcodes) { + //noinspection NestedTryStatement + try { + final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); + final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); + synchronized (deltaNm) { + deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + } + + final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? + Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); + if (distanceNm > maxDeltaNm) { + LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + + "which is {} meters from the original point (max is {} meters).", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, + ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + errors.incrementAndGet(); + } + } catch (final UnknownMapcodeException unknownMapcodeException) { + LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point); + errors.incrementAndGet(); + } } - } catch (final UnknownMapcodeException unknownMapcodeException) { - LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point); - errors.incrementAndGet(); } - } + }); + + // Break out of loop and process next value. + break; + + } catch (final RejectedExecutionException ignored) { + + // Perfectly fine; buffer is full. Just wait a bit and re-enter while loop. + Thread.sleep(100); } - }); + } } } catch (final EOFException e) { // OK. From c1ed602de4d0d75f2e925ffe17a815c5339e7f55 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 15:41:12 +0200 Subject: [PATCH 5/8] Fixed heap space problem in tests --- .../java/com/mapcode/EncodeDecodeTest.java | 132 ++++++++---------- .../java/com/mapcode/ReferenceFileTest.java | 23 ++- 2 files changed, 67 insertions(+), 88 deletions(-) diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index d1e7457..353920d 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -37,7 +37,6 @@ public class EncodeDecodeTest { new GsonBuilder().serializeSpecialFloatingPointValues().create(); private static final int NUMBER_OF_POINTS = 5000; - private static final int NUMBER_OF_TASKS = NUMBER_OF_POINTS * Territory.values().length; private static final int LOG_LINE_EVERY = 500; @Test @@ -61,12 +60,9 @@ private static void doEncodeDecode(final long seed) throws InterruptedException final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger tasks = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors(); + final int threads = Runtime.getRuntime().availableProcessors() * 2; LOG.info("encodeDecodeTest: Starting {} threads...", threads); - final ExecutorService executor = new ThreadPoolExecutor( - threads, threads, // Fixed number of threads. - 0L, TimeUnit.MILLISECONDS, // No keep-alive. - new LinkedBlockingQueue(25000)); // Reasonable-size blocking queue. + final ExecutorService executor = Executors.newFixedThreadPool(threads); final Random randomGenerator = new Random(seed); for (int i = 0; i < NUMBER_OF_POINTS; i++) { @@ -85,84 +81,70 @@ private static void doEncodeDecode(final long seed) throws InterruptedException assertEquals("encodeToInternational failed, result=" + resultsAll, resultsAll.get(resultsAll.size() - 1), mapcodeInternational); - // Walk through the list in reverse order to get International first. - for (final Territory territory : Territory.values()) { - while (true) { - try { - executor.execute(new Runnable() { - - @Override - public void run() { - try { - final int count = tasks.incrementAndGet(); - if ((count % LOG_LINE_EVERY) == 0) { - LOG.info("encodeDecodeTest: #{}/{}", count, NUMBER_OF_TASKS); - } + executor.execute(new Runnable() { - final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); - for (final Mapcode mapcode : resultsLimited) { - - // Check if the territory matches. - assertEquals(territory, mapcode.getTerritory()); - - // Check max distance. - final String codePrecision0 = mapcode.getCode(0); - final String codePrecision1 = mapcode.getCode(1); - final String codePrecision2 = mapcode.getCode(2); - - final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); - final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); - final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); - - final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); - final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); - final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); - - if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); - errors.getAndIncrement(); - } - if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); - errors.getAndIncrement(); - } - if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { - LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); - errors.getAndIncrement(); - } - - // Check conversion from/to alphabets. - for (final Alphabet alphabet : Alphabet.values()) { - final String mapcodeAlphabet = mapcode.getCode(alphabet); - final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); - if (!codePrecision0.equals(mapcodeAscii)) { - LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + - ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); - } - } - } - } catch (final Exception e) { - LOG.error("encodeDecodeTest: Unexpected exception: ", e); - errors.getAndIncrement(); - } - } - }); + @Override + public void run() { + final int count = tasks.getAndIncrement(); + if ((count % LOG_LINE_EVERY) == 0) { + LOG.info("encodeDecodeTest: #{}/{}", count, NUMBER_OF_POINTS); + } + + // Walk through the list in reverse order to get International first. + for (final Territory territory : Territory.values()) { + try { + final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); + for (final Mapcode mapcode : resultsLimited) { + + // Check if the territory matches. + assertEquals(territory, mapcode.getTerritory()); - // Break out of loop and process next value. - break; + // Check max distance. + final String codePrecision0 = mapcode.getCode(0); + final String codePrecision1 = mapcode.getCode(1); + final String codePrecision2 = mapcode.getCode(2); - } catch (final RejectedExecutionException ignored) { + final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory); + final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory); + final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory); - // Perfectly fine; buffer is full. Just wait a bit and re-enter while loop. - LOG.info("encodeDecodeTest: buffer full, waiting, executed {} tasks so far", tasks); - Thread.sleep(1000); + final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0); + final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1); + final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2); + + if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0)); + errors.getAndIncrement(); + } + if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1)); + errors.getAndIncrement(); + } + if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) { + LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2)); + errors.getAndIncrement(); + } + + // Check conversion from/to alphabets. + for (final Alphabet alphabet : Alphabet.values()) { + final String mapcodeAlphabet = mapcode.getCode(alphabet); + final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet); + if (!codePrecision0.equals(mapcodeAscii)) { + LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 + + ", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii); + } + } + } + } catch (final Exception e) { + LOG.error("encodeDecodeTest: Unexpected exception: ", e); + errors.getAndIncrement(); + } } } - } + }); } executor.shutdown(); executor.awaitTermination(60, TimeUnit.SECONDS); assertEquals("Found errors", 0, errors.get()); - LOG.info("encodeDecodeTest: executed {} tasks", tasks); } } diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index ed12476..0ddb5b7 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -115,31 +115,21 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti // Reset error count. final AtomicLong deltaNm = new AtomicLong(0); final AtomicInteger errors = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors(); + final AtomicInteger tasks = new AtomicInteger(0); + final int threads = Runtime.getRuntime().availableProcessors() * 2; LOG.info("checkFile: Starting {} threads...", threads); - final ExecutorService executor = new ThreadPoolExecutor( - threads, threads, // Fixed number of threads. - 0L, TimeUnit.MILLISECONDS, // No keep-alive. - new LinkedBlockingQueue(1000)); // Reasonable-size blocking queue. + final ExecutorService executor = Executors.newFixedThreadPool(threads); // Open data file. final ChunkedFile chunkedFile = new ChunkedFile(baseFileName); try { - int i = 1; //noinspection InfiniteLoopStatement while (true) { // Get next record. @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); - if (((i % LOG_LINE_EVERY) == 0)) { - LOG.debug("checkFile: #{}, file={}", i, chunkedFile.fileName); - LOG.debug("checkFile: lat/lon = {}", reference.point); - LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); - } - ++i; - while (true) { try { // Add task. This may throw an exception if the queue is full. Retry in that case. @@ -147,6 +137,13 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti @Override public void run() { + final int count = tasks.getAndIncrement(); + if (((count % LOG_LINE_EVERY) == 0)) { + LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); + LOG.debug("checkFile: lat/lon = {}", reference.point); + LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); + } + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. final List results = MapcodeCodec.encode( reference.point.getLatDeg(), reference.point.getLonDeg()); From 40918c879a99d4bc07828d428177b4ad2749d763 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 17:42:13 +0200 Subject: [PATCH 6/8] Fixed heap space problem in tests --- .../java/com/mapcode/ReferenceFileTest.java | 242 ++++++++---------- 1 file changed, 113 insertions(+), 129 deletions(-) diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index 0ddb5b7..4763bf7 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -124,148 +124,132 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti final ChunkedFile chunkedFile = new ChunkedFile(baseFileName); try { - //noinspection InfiniteLoopStatement - while (true) { - - // Get next record. - @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); - - while (true) { - try { - // Add task. This may throw an exception if the queue is full. Retry in that case. - executor.execute(new Runnable() { - - @Override - public void run() { - final int count = tasks.getAndIncrement(); - if (((count % LOG_LINE_EVERY) == 0)) { - LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); - LOG.debug("checkFile: lat/lon = {}", reference.point); - LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); - } + // Get next record. + @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); + + // Add task. This may throw an exception if the queue is full. Retry in that case. + executor.execute(new Runnable() { + + @Override + public void run() { + final int count = tasks.getAndIncrement(); + if (((count % LOG_LINE_EVERY) == 0)) { + LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); + LOG.debug("checkFile: lat/lon = {}", reference.point); + LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); + } - // Encode lat/lon to series of mapcodes and check the resulting mapcodes. - final List results = MapcodeCodec.encode( - reference.point.getLatDeg(), reference.point.getLonDeg()); + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. + final List results = MapcodeCodec.encode( + reference.point.getLatDeg(), reference.point.getLonDeg()); - // Check the number of mapcodes. - if (results.isEmpty()) { - LOG.error("checkFile: encode fails, no results found for reference={}", reference); - errors.incrementAndGet(); - } - - // Check encodeToInternational. - final Mapcode resultInternational = MapcodeCodec.encodeToInternational( - reference.point.getLatDeg(), reference.point.getLonDeg()); - final Mapcode expectedInternational = results.get(results.size() - 1); - if (!resultInternational.equals(expectedInternational)) { - LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", - expectedInternational, resultInternational, reference); - errors.incrementAndGet(); - } + // Check the number of mapcodes. + if (results.isEmpty()) { + LOG.error("checkFile: encode fails, no results found for reference={}", reference); + errors.incrementAndGet(); + } - // Check the size of the results. - if (reference.mapcodes.size() != results.size()) { - final ArrayList resultsConverted = new ArrayList(results.size()); - for (final Mapcode mapcode : results) { - resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); - } - LOG.error("checkFile: Incorrect number of results:" + - "\n lat/lon = {}" + - "\n expected = #{}: {} results," + - "\n actual = #{}: {} results\n", - reference.point, - reference.mapcodes.size(), - GSON.toJson(reference.mapcodes), - results.size(), - GSON.toJson(resultsConverted)); - errors.incrementAndGet(); - } + // Check encodeToInternational. + final Mapcode resultInternational = MapcodeCodec.encodeToInternational( + reference.point.getLatDeg(), reference.point.getLonDeg()); + final Mapcode expectedInternational = results.get(results.size() - 1); + if (!resultInternational.equals(expectedInternational)) { + LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", + expectedInternational, resultInternational, reference); + errors.incrementAndGet(); + } - // For every mapcode in the result set, check if it is contained in the reference set. - int precision = 0; - for (final Mapcode result : results) { - boolean found = false; - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; - } - } - } - if (!found) { - - // This does not fail the test, but rather produces an ERROR in the log file. - // It indicates a discrepancy in the C and Java implementations. - LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + - "ref={}\n" + "new={}", - result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); - errors.incrementAndGet(); - } - } + // Check the size of the results. + if (reference.mapcodes.size() != results.size()) { + final ArrayList resultsConverted = new ArrayList(results.size()); + for (final Mapcode mapcode : results) { + resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); + } + LOG.error("checkFile: Incorrect number of results:" + + "\n lat/lon = {}" + + "\n expected = #{}: {} results," + + "\n actual = #{}: {} results\n", + reference.point, + reference.mapcodes.size(), + GSON.toJson(reference.mapcodes), + results.size(), + GSON.toJson(resultsConverted)); + errors.incrementAndGet(); + } - // For every Mapcode in the reference set, check if it is contained in the result set. - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - boolean found = false; - for (final Mapcode result : results) { - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; - } - } - } - if (!found) { - LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + - "ref={}", - referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, - GSON.toJson(reference)); - errors.incrementAndGet(); - } + // For every mapcode in the result set, check if it is contained in the reference set. + int precision = 0; + for (final Mapcode result : results) { + boolean found = false; + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; } + } + } + if (!found) { + + // This does not fail the test, but rather produces an ERROR in the log file. + // It indicates a discrepancy in the C and Java implementations. + LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + + "ref={}\n" + "new={}", + result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + errors.incrementAndGet(); + } + } - // Check distance of decoded point to reference point. - for (final MapcodeRec mapcodeRec : reference.mapcodes) { - //noinspection NestedTryStatement - try { - final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); - final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); - synchronized (deltaNm) { - deltaNm.set(Math.max(deltaNm.get(), distanceNm)); - } - - final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? - Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); - if (distanceNm > maxDeltaNm) { - LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + - "which is {} meters from the original point (max is {} meters).", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, - ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); - errors.incrementAndGet(); - } - } catch (final UnknownMapcodeException unknownMapcodeException) { - LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point); - errors.incrementAndGet(); - } + // For every Mapcode in the reference set, check if it is contained in the result set. + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + boolean found = false; + for (final Mapcode result : results) { + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; } } - }); - - // Break out of loop and process next value. - break; + } + if (!found) { + LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + + "ref={}", + referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, + GSON.toJson(reference)); + errors.incrementAndGet(); + } + } - } catch (final RejectedExecutionException ignored) { + // Check distance of decoded point to reference point. + for (final MapcodeRec mapcodeRec : reference.mapcodes) { + //noinspection NestedTryStatement + try { + final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); + final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); + synchronized (deltaNm) { + deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + } - // Perfectly fine; buffer is full. Just wait a bit and re-enter while loop. - Thread.sleep(100); + final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? + Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); + if (distanceNm > maxDeltaNm) { + LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + + "which is {} meters from the original point (max is {} meters).", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, + ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + errors.incrementAndGet(); + } + } catch (final UnknownMapcodeException unknownMapcodeException) { + LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point); + errors.incrementAndGet(); + } } } - } + }); } catch (final EOFException e) { // OK. } finally { From 77b6406cdd41c897ea7791bb835f65f2eab55a4f Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 18:04:16 +0200 Subject: [PATCH 7/8] Redone changes --- .../java/com/mapcode/EncodeDecodeTest.java | 17 +- .../java/com/mapcode/ReferenceFileTest.java | 215 +++++++++--------- 2 files changed, 119 insertions(+), 113 deletions(-) diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index 353920d..0674726 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -60,7 +60,7 @@ private static void doEncodeDecode(final long seed) throws InterruptedException final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger tasks = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors() * 2; + final int threads = Runtime.getRuntime().availableProcessors(); LOG.info("encodeDecodeTest: Starting {} threads...", threads); final ExecutorService executor = Executors.newFixedThreadPool(threads); @@ -85,14 +85,14 @@ private static void doEncodeDecode(final long seed) throws InterruptedException @Override public void run() { - final int count = tasks.getAndIncrement(); + final int count = tasks.incrementAndGet(); if ((count % LOG_LINE_EVERY) == 0) { LOG.info("encodeDecodeTest: #{}/{}", count, NUMBER_OF_POINTS); } - // Walk through the list in reverse order to get International first. - for (final Territory territory : Territory.values()) { - try { + try { + // Walk through the list in reverse order to get International first. + for (final Territory territory : Territory.values()) { final List resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory); for (final Mapcode mapcode : resultsLimited) { @@ -135,10 +135,10 @@ public void run() { } } } - } catch (final Exception e) { - LOG.error("encodeDecodeTest: Unexpected exception: ", e); - errors.getAndIncrement(); } + } catch (final UnknownMapcodeException e) { + LOG.error("encodeDecodeTest: Unknown mapcode exception", e); + errors.getAndIncrement(); } } }); @@ -146,5 +146,6 @@ public void run() { executor.shutdown(); executor.awaitTermination(60, TimeUnit.SECONDS); assertEquals("Found errors", 0, errors.get()); + LOG.info("encodeDecodeTest: Executed {} tasks", tasks); } } diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index 4763bf7..2fb9b16 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -116,7 +116,8 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti final AtomicLong deltaNm = new AtomicLong(0); final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger tasks = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors() * 2; + + final int threads = Runtime.getRuntime().availableProcessors(); LOG.info("checkFile: Starting {} threads...", threads); final ExecutorService executor = Executors.newFixedThreadPool(threads); @@ -124,132 +125,136 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti final ChunkedFile chunkedFile = new ChunkedFile(baseFileName); try { - // Get next record. - @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); + //noinspection InfiniteLoopStatement + while (true) { - // Add task. This may throw an exception if the queue is full. Retry in that case. - executor.execute(new Runnable() { + // Get next record. + @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); - @Override - public void run() { - final int count = tasks.getAndIncrement(); - if (((count % LOG_LINE_EVERY) == 0)) { - LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); - LOG.debug("checkFile: lat/lon = {}", reference.point); - LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); - } + final int count = tasks.getAndIncrement(); + if (((count % LOG_LINE_EVERY) == 0)) { + LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); + LOG.debug("checkFile: lat/lon = {}", reference.point); + LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); + } - // Encode lat/lon to series of mapcodes and check the resulting mapcodes. - final List results = MapcodeCodec.encode( - reference.point.getLatDeg(), reference.point.getLonDeg()); + // Add task. This may throw an exception if the queue is full. Retry in that case. + executor.execute(new Runnable() { - // Check the number of mapcodes. - if (results.isEmpty()) { - LOG.error("checkFile: encode fails, no results found for reference={}", reference); - errors.incrementAndGet(); - } + @Override + public void run() { + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. + final List results = MapcodeCodec.encode( + reference.point.getLatDeg(), reference.point.getLonDeg()); - // Check encodeToInternational. - final Mapcode resultInternational = MapcodeCodec.encodeToInternational( - reference.point.getLatDeg(), reference.point.getLonDeg()); - final Mapcode expectedInternational = results.get(results.size() - 1); - if (!resultInternational.equals(expectedInternational)) { - LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", - expectedInternational, resultInternational, reference); - errors.incrementAndGet(); - } - - // Check the size of the results. - if (reference.mapcodes.size() != results.size()) { - final ArrayList resultsConverted = new ArrayList(results.size()); - for (final Mapcode mapcode : results) { - resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); + // Check the number of mapcodes. + if (results.isEmpty()) { + LOG.error("checkFile: encode fails, no results found for reference={}", reference); + errors.incrementAndGet(); } - LOG.error("checkFile: Incorrect number of results:" + - "\n lat/lon = {}" + - "\n expected = #{}: {} results," + - "\n actual = #{}: {} results\n", - reference.point, - reference.mapcodes.size(), - GSON.toJson(reference.mapcodes), - results.size(), - GSON.toJson(resultsConverted)); - errors.incrementAndGet(); - } - // For every mapcode in the result set, check if it is contained in the reference set. - int precision = 0; - for (final Mapcode result : results) { - boolean found = false; - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; - } - } + // Check encodeToInternational. + final Mapcode resultInternational = MapcodeCodec.encodeToInternational( + reference.point.getLatDeg(), reference.point.getLonDeg()); + final Mapcode expectedInternational = results.get(results.size() - 1); + if (!resultInternational.equals(expectedInternational)) { + LOG.error("checkFile: encodeToInternational fails, expected={}, got={} for reference", + expectedInternational, resultInternational, reference); + errors.incrementAndGet(); } - if (!found) { - // This does not fail the test, but rather produces an ERROR in the log file. - // It indicates a discrepancy in the C and Java implementations. - LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + - "ref={}\n" + "new={}", - result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + // Check the size of the results. + if (reference.mapcodes.size() != results.size()) { + final ArrayList resultsConverted = new ArrayList(results.size()); + for (final Mapcode mapcode : results) { + resultsConverted.add(new MapcodeRec(mapcode.getCode(2), mapcode.getTerritory())); + } + LOG.error("checkFile: Incorrect number of results:" + + "\n lat/lon = {}" + + "\n expected = #{}: {} results," + + "\n actual = #{}: {} results\n", + reference.point, + reference.mapcodes.size(), + GSON.toJson(reference.mapcodes), + results.size(), + GSON.toJson(resultsConverted)); errors.incrementAndGet(); } - } - // For every Mapcode in the reference set, check if it is contained in the result set. - for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { - precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; - boolean found = false; + // For every mapcode in the result set, check if it is contained in the reference set. + int precision = 0; for (final Mapcode result : results) { - if (referenceMapcodeRec.territory.equals(result.getTerritory())) { - if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { - found = true; - break; + boolean found = false; + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } } } + if (!found) { + + // This does not fail the test, but rather produces an ERROR in the log file. + // It indicates a discrepancy in the C and Java implementations. + LOG.error("checkFile: Created '{}' at {} which is not present in the reference file!\n" + + "ref={}\n" + "new={}", + result.getCode(precision), reference.point, GSON.toJson(reference), GSON.toJson(result)); + errors.incrementAndGet(); + } } - if (!found) { - LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + - "ref={}", - referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, - GSON.toJson(reference)); - errors.incrementAndGet(); - } - } - // Check distance of decoded point to reference point. - for (final MapcodeRec mapcodeRec : reference.mapcodes) { - //noinspection NestedTryStatement - try { - final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); - final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); - synchronized (deltaNm) { - deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + // For every Mapcode in the reference set, check if it is contained in the result set. + for (final MapcodeRec referenceMapcodeRec : reference.mapcodes) { + precision = (referenceMapcodeRec.mapcode.lastIndexOf('-') > 4) ? 2 : 0; + boolean found = false; + for (final Mapcode result : results) { + if (referenceMapcodeRec.territory.equals(result.getTerritory())) { + if (referenceMapcodeRec.mapcode.equals(result.getCode(precision))) { + found = true; + break; + } + } } + if (!found) { + LOG.error("checkFile: Found '{} {}' at {} in reference file, not produced by new decoder!\n" + + "ref={}", + referenceMapcodeRec.territory, referenceMapcodeRec.mapcode, reference.point, + GSON.toJson(reference)); + errors.incrementAndGet(); + } + } + + // Check distance of decoded point to reference point. + for (final MapcodeRec mapcodeRec : reference.mapcodes) { + //noinspection NestedTryStatement + try { + final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); + final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); + synchronized (deltaNm) { + deltaNm.set(Math.max(deltaNm.get(), distanceNm)); + } - final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? - Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); - if (distanceNm > maxDeltaNm) { - LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + - "which is {} meters from the original point (max is {} meters).", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, - ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + final long maxDeltaNm = (long) (((mapcodeRec.mapcode.lastIndexOf('-') > 4) ? + Mapcode.getSafeMaxOffsetInMeters(2) : Mapcode.getSafeMaxOffsetInMeters(0)) * 1000000.0); + if (distanceNm > maxDeltaNm) { + LOG.error("Mapcode {} {} was generated for point {}, but decodes to point {} " + + "which is {} meters from the original point (max is {} meters).", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point, result, + ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); + errors.incrementAndGet(); + } + } catch (final UnknownMapcodeException unknownMapcodeException) { + LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", + mapcodeRec.territory, mapcodeRec.mapcode, reference.point); errors.incrementAndGet(); } - } catch (final UnknownMapcodeException unknownMapcodeException) { - LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point); - errors.incrementAndGet(); } } - } - }); + }); + } } catch (final EOFException e) { // OK. } finally { @@ -259,7 +264,7 @@ public void run() { executor.awaitTermination(60, TimeUnit.SECONDS); assertEquals(0, errors.get()); assertEquals("Found errors", 0, errors.get()); - LOG.debug("checkFile: Maximum delta for this testset = {}m", ((double) deltaNm.get()) / 1000000.0); + LOG.debug("checkFile: Maximum delta for this testset = {}m, executed {} tasks", ((double) deltaNm.get()) / 1000000.0, tasks); } private static class MapcodeRec { From c69e912b7fcba1d7816b52d72c87a17c28f474c8 Mon Sep 17 00:00:00 2001 From: Rijn Buve Date: Thu, 9 Jul 2015 18:28:06 +0200 Subject: [PATCH 8/8] Redone changes --- .../java/com/mapcode/EncodeDecodeTest.java | 2 +- .../java/com/mapcode/ReferenceFileTest.java | 34 +++++++++---------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/test/java/com/mapcode/EncodeDecodeTest.java b/src/test/java/com/mapcode/EncodeDecodeTest.java index 0674726..3836a5b 100644 --- a/src/test/java/com/mapcode/EncodeDecodeTest.java +++ b/src/test/java/com/mapcode/EncodeDecodeTest.java @@ -60,7 +60,7 @@ private static void doEncodeDecode(final long seed) throws InterruptedException final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger tasks = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors(); + final int threads = Runtime.getRuntime().availableProcessors() * 2; LOG.info("encodeDecodeTest: Starting {} threads...", threads); final ExecutorService executor = Executors.newFixedThreadPool(threads); diff --git a/src/test/java/com/mapcode/ReferenceFileTest.java b/src/test/java/com/mapcode/ReferenceFileTest.java index 2fb9b16..a76093a 100644 --- a/src/test/java/com/mapcode/ReferenceFileTest.java +++ b/src/test/java/com/mapcode/ReferenceFileTest.java @@ -57,7 +57,7 @@ public class ReferenceFileTest { private static final String BOUNDARIES_REFERENCE_FILE = "/boundaries.txt"; private static final String BOUNDARIES_REFERENCE_FILE_HP = "/boundaries_hp.txt"; - private static final int LOG_LINE_EVERY = 25000; + private static final int LOG_LINE_EVERY = 10000; @SuppressWarnings("JUnitTestMethodWithNoAssertions") @Test @@ -117,7 +117,7 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger tasks = new AtomicInteger(0); - final int threads = Runtime.getRuntime().availableProcessors(); + final int threads = Runtime.getRuntime().availableProcessors() * 2; LOG.info("checkFile: Starting {} threads...", threads); final ExecutorService executor = Executors.newFixedThreadPool(threads); @@ -131,18 +131,16 @@ private static void checkFile(@Nonnull final String baseFileName) throws Excepti // Get next record. @Nonnull final ReferenceRec reference = getNextReferenceRecord(chunkedFile); - final int count = tasks.getAndIncrement(); - if (((count % LOG_LINE_EVERY) == 0)) { - LOG.debug("checkFile: #{}, file={}", count, chunkedFile.fileName); - LOG.debug("checkFile: lat/lon = {}", reference.point); - LOG.debug("checkFile: expected = #{}: {}", reference.mapcodes.size(), GSON.toJson(reference.mapcodes)); - } - // Add task. This may throw an exception if the queue is full. Retry in that case. executor.execute(new Runnable() { @Override public void run() { + final int count = tasks.getAndIncrement(); + if (((count % LOG_LINE_EVERY) == 0)) { + LOG.info("checkFile: #{}, file={}", count, chunkedFile.fileName); + } + // Encode lat/lon to series of mapcodes and check the resulting mapcodes. final List results = MapcodeCodec.encode( reference.point.getLatDeg(), reference.point.getLonDeg()); @@ -227,10 +225,10 @@ public void run() { } } - // Check distance of decoded point to reference point. - for (final MapcodeRec mapcodeRec : reference.mapcodes) { - //noinspection NestedTryStatement - try { + try { + // Check distance of decoded point to reference point. + for (final MapcodeRec mapcodeRec : reference.mapcodes) { + //noinspection NestedTryStatement final Point result = MapcodeCodec.decode(mapcodeRec.mapcode, mapcodeRec.territory); final long distanceNm = (long) (Point.distanceInMeters(reference.point, result) * 1000000.0); synchronized (deltaNm) { @@ -246,11 +244,11 @@ public void run() { ((double) distanceNm) / 1000000.0, ((double) maxDeltaNm) / 1000000.0); errors.incrementAndGet(); } - } catch (final UnknownMapcodeException unknownMapcodeException) { - LOG.error("Mapcode {} {} was generated for point {}, but cannot be decoded.", - mapcodeRec.territory, mapcodeRec.mapcode, reference.point); - errors.incrementAndGet(); } + } catch (final UnknownMapcodeException e) { + LOG.error("Mapcode was generated for point {}, but cannot be decoded, msg={}", + reference.point, e.getMessage()); + errors.incrementAndGet(); } } }); @@ -264,7 +262,7 @@ public void run() { executor.awaitTermination(60, TimeUnit.SECONDS); assertEquals(0, errors.get()); assertEquals("Found errors", 0, errors.get()); - LOG.debug("checkFile: Maximum delta for this testset = {}m, executed {} tasks", ((double) deltaNm.get()) / 1000000.0, tasks); + LOG.info("checkFile: Maximum delta for this testset = {}m, executed {} tasks", ((double) deltaNm.get()) / 1000000.0, tasks); } private static class MapcodeRec {