Claude Code tire-kicking: generate some unit tests
This commit is contained in:
parent
c375665a6d
commit
5a30ab0d3f
7 changed files with 1025 additions and 0 deletions
84
CLAUDE.md
Normal file
84
CLAUDE.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Dynmap is a dynamic web mapping plugin/mod for Minecraft servers. It's a multi-platform project supporting Spigot/PaperMC, Forge, and Fabric across multiple Minecraft versions (1.12.2 - 1.21.x).
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
# Build all platforms (requires JDK 21 as default)
|
||||
./gradlew setup build
|
||||
|
||||
# Build outputs go to /target directory
|
||||
|
||||
# Build specific module (for faster iteration, but NOT for PR submissions)
|
||||
./gradlew :fabric-1.18:build
|
||||
|
||||
# Forge 1.12.2 (requires JDK 8 - set JAVA_HOME accordingly)
|
||||
cd oldgradle
|
||||
./gradlew setup build
|
||||
```
|
||||
|
||||
**JDK Requirements:**
|
||||
- Default: JDK 21
|
||||
- Forge 1.12.2 (oldgradle): JDK 8 strictly required
|
||||
- Runtime targets: JDK 8 (1.16-), JDK 16 (1.17.x), JDK 17 (1.18-1.20.4), JDK 21 (1.20.5+)
|
||||
|
||||
## Architecture
|
||||
|
||||
### Module Structure (71 modules total)
|
||||
|
||||
**Core Shared Modules:**
|
||||
- `DynmapCoreAPI/` - Stable public API for external plugins/mods (markers, mod support, rendering)
|
||||
- `DynmapCore/` - Internal shared implementation (NOT stable - subject to breaking changes)
|
||||
- `dynmap-api/` - Bukkit-specific public API
|
||||
|
||||
**Platform Implementations:**
|
||||
- `spigot/` - Bukkit/PaperMC implementation
|
||||
- `bukkit-helper-*` - Version-specific NMS code (25 versions: 1.13-1.21)
|
||||
- `fabric-*` - Fabric mod implementations (14 versions: 1.14.4-1.21.11)
|
||||
- `forge-*` - Forge mod implementations (14 versions: 1.14.4-1.21.11)
|
||||
|
||||
### Dependency Flow
|
||||
```
|
||||
External Plugins/Mods
|
||||
↓
|
||||
DynmapCoreAPI (stable, published to repo.mikeprimm.com)
|
||||
↓
|
||||
DynmapCore (internal, unstable)
|
||||
↓
|
||||
Platform-specific modules (Spigot, Fabric, Forge)
|
||||
```
|
||||
|
||||
### Key Components in DynmapCore
|
||||
- `MapManager` - Tile/map rendering orchestration
|
||||
- `DynmapCore.java` - Main coordination hub (~3,100 lines)
|
||||
- `storage/` - Storage backends (FileTree, MySQL, PostgreSQL, SQLite, S3)
|
||||
- `hdmap/` - HD map rendering (block models, shaders, textures)
|
||||
- `web/` - Embedded Jetty server with servlets
|
||||
- `markers/` - Marker system implementation
|
||||
|
||||
## Critical Contribution Rules
|
||||
|
||||
**PRs must build and test on ALL platforms including oldgradle. Changes to DynmapCore/DynmapCoreAPI require testing on all platforms.**
|
||||
|
||||
- **Java 8 compatibility required** - Code must compile and run on Java 8
|
||||
- **Java only** - No Kotlin, Scala, or other JVM languages
|
||||
- **No dependency updates** - Library versions are tied to platform compatibility
|
||||
- **No platform-specific code** - Must work on Windows, Linux (x86/ARM), macOS, Docker
|
||||
- **Small PRs only** - One feature per PR, no style/formatting changes
|
||||
- **No mod-specific code** - Use Dynmap APIs instead; external mods should depend on DynmapCoreAPI
|
||||
- **Apache License v2** - All code must be compatible
|
||||
|
||||
## Testing
|
||||
|
||||
No automated tests exist. Verification is done by:
|
||||
1. Building all platforms successfully (`./gradlew setup build` AND `cd oldgradle && ./gradlew setup build`)
|
||||
2. Manual testing on target Minecraft server platforms
|
||||
|
||||
## Storage Backends
|
||||
|
||||
Dynmap supports: FileTree (default), MySQL/MariaDB, PostgreSQL, SQLite, MS SQL Server, AWS S3
|
||||
|
|
@ -26,6 +26,18 @@ dependencies {
|
|||
implementation 'io.github.linktosriram.s3lite:util:0.0.2-SNAPSHOT'
|
||||
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.1'
|
||||
implementation 'com.sun.xml.bind:jaxb-impl:3.0.0'
|
||||
// Test dependencies (Java 8 compatible versions)
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.mockito:mockito-core:4.11.0'
|
||||
testImplementation 'org.assertj:assertj-core:3.24.2'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnit()
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
exceptionFormat "full"
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
package org.dynmap.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import java.io.IOException;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BufferInputStreamTest {
|
||||
|
||||
@Test
|
||||
public void testConstructorWithBuffer() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertEquals(5, stream.length());
|
||||
assertSame(data, stream.buffer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorWithBufferAndLength() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data, 3);
|
||||
assertEquals(3, stream.length());
|
||||
assertSame(data, stream.buffer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSingleByte() {
|
||||
byte[] data = {10, 20, 30};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertEquals(10, stream.read());
|
||||
assertEquals(20, stream.read());
|
||||
assertEquals(30, stream.read());
|
||||
assertEquals(-1, stream.read()); // EOF
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSingleByteUnsigned() {
|
||||
// Test that bytes are returned as unsigned (0-255)
|
||||
byte[] data = {(byte) 255, (byte) 128};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertEquals(255, stream.read());
|
||||
assertEquals(128, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadArray() throws IOException {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
byte[] buffer = new byte[3];
|
||||
int bytesRead = stream.read(buffer, 0, 3);
|
||||
assertEquals(3, bytesRead);
|
||||
assertEquals(1, buffer[0]);
|
||||
assertEquals(2, buffer[1]);
|
||||
assertEquals(3, buffer[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadArrayPartial() throws IOException {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
byte[] buffer = new byte[5];
|
||||
int bytesRead = stream.read(buffer, 0, 5);
|
||||
assertEquals(3, bytesRead);
|
||||
assertEquals(1, buffer[0]);
|
||||
assertEquals(2, buffer[1]);
|
||||
assertEquals(3, buffer[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadArrayAtEOF() throws IOException {
|
||||
byte[] data = {1, 2};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.read();
|
||||
stream.read();
|
||||
byte[] buffer = new byte[5];
|
||||
int bytesRead = stream.read(buffer, 0, 5);
|
||||
assertEquals(-1, bytesRead);
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void testReadArrayNullBuffer() throws IOException {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.read(null, 0, 3);
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void testReadArrayNegativeOffset() throws IOException {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
byte[] buffer = new byte[5];
|
||||
stream.read(buffer, -1, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAvailable() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertEquals(5, stream.available());
|
||||
stream.read();
|
||||
assertEquals(4, stream.available());
|
||||
stream.read();
|
||||
stream.read();
|
||||
assertEquals(2, stream.available());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkip() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
long skipped = stream.skip(2);
|
||||
assertEquals(2, skipped);
|
||||
assertEquals(3, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipPastEnd() {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
long skipped = stream.skip(10);
|
||||
assertEquals(3, skipped);
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipNegative() {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.read();
|
||||
long skipped = stream.skip(-5);
|
||||
assertEquals(0, skipped);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarkSupported() {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertTrue(stream.markSupported());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarkAndReset() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.read();
|
||||
stream.read();
|
||||
stream.mark(0); // Mark at position 2
|
||||
assertEquals(3, stream.read());
|
||||
assertEquals(4, stream.read());
|
||||
stream.reset();
|
||||
assertEquals(3, stream.read()); // Back to position 2
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetWithoutMark() {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.read();
|
||||
stream.read();
|
||||
stream.reset(); // Should reset to 0 (default mark)
|
||||
assertEquals(1, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClose() {
|
||||
byte[] data = {1, 2, 3};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
stream.close(); // Should not throw
|
||||
// Stream should still be usable after close (no-op)
|
||||
assertEquals(1, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyBuffer() {
|
||||
byte[] data = {};
|
||||
BufferInputStream stream = new BufferInputStream(data);
|
||||
assertEquals(0, stream.available());
|
||||
assertEquals(-1, stream.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLengthVsBufferLength() {
|
||||
byte[] data = {1, 2, 3, 4, 5};
|
||||
BufferInputStream stream = new BufferInputStream(data, 2);
|
||||
assertEquals(2, stream.available());
|
||||
assertEquals(1, stream.read());
|
||||
assertEquals(2, stream.read());
|
||||
assertEquals(-1, stream.read()); // EOF at specified length
|
||||
}
|
||||
}
|
||||
249
DynmapCore/src/test/java/org/dynmap/utils/DynIntHashMapTest.java
Normal file
249
DynmapCore/src/test/java/org/dynmap/utils/DynIntHashMapTest.java
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
package org.dynmap.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import java.util.List;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class DynIntHashMapTest {
|
||||
|
||||
@Test
|
||||
public void testDefaultConstructor() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorWithCapacity() {
|
||||
DynIntHashMap map = new DynIntHashMap(100);
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructorWithCapacityAndLoadFactor() {
|
||||
DynIntHashMap map = new DynIntHashMap(100, 0.5f);
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructorNegativeCapacity() {
|
||||
new DynIntHashMap(-1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructorZeroLoadFactor() {
|
||||
new DynIntHashMap(10, 0.0f);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConstructorNegativeLoadFactor() {
|
||||
new DynIntHashMap(10, -0.5f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyConstructor() {
|
||||
DynIntHashMap original = new DynIntHashMap();
|
||||
original.put(1, "one");
|
||||
original.put(2, "two");
|
||||
|
||||
DynIntHashMap copy = new DynIntHashMap(original);
|
||||
assertEquals(2, copy.size());
|
||||
assertEquals("one", copy.get(1));
|
||||
assertEquals("two", copy.get(2));
|
||||
|
||||
// Verify it's a deep copy
|
||||
original.put(1, "modified");
|
||||
assertEquals("one", copy.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGet() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
assertNull(map.put(1, "one"));
|
||||
assertEquals("one", map.get(1));
|
||||
assertEquals(1, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutReplace() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
Object oldValue = map.put(1, "ONE");
|
||||
assertEquals("one", oldValue);
|
||||
assertEquals("ONE", map.get(1));
|
||||
assertEquals(1, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutNullValue() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, null);
|
||||
assertNull(map.get(1));
|
||||
assertTrue(map.containsKey(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNonExistent() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
assertNull(map.get(999));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsKey() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
assertTrue(map.containsKey(1));
|
||||
assertFalse(map.containsKey(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsValue() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
assertTrue(map.containsValue("one"));
|
||||
assertTrue(map.containsValue("two"));
|
||||
assertFalse(map.containsValue("three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsValueNull() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, null);
|
||||
assertTrue(map.containsValue(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
|
||||
Object removed = map.remove(1);
|
||||
assertEquals("one", removed);
|
||||
assertEquals(1, map.size());
|
||||
assertFalse(map.containsKey(1));
|
||||
assertTrue(map.containsKey(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonExistent() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
|
||||
Object removed = map.remove(999);
|
||||
assertNull(removed);
|
||||
assertEquals(1, map.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
map.put(3, "three");
|
||||
|
||||
map.clear();
|
||||
assertTrue(map.isEmpty());
|
||||
assertEquals(0, map.size());
|
||||
assertNull(map.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
map.put(1, "one");
|
||||
assertFalse(map.isEmpty());
|
||||
|
||||
map.remove(1);
|
||||
assertTrue(map.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeysWithValue() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "value");
|
||||
map.put(2, "value");
|
||||
map.put(3, "other");
|
||||
|
||||
List<Integer> keys = map.keysWithValue("value");
|
||||
assertEquals(2, keys.size());
|
||||
assertTrue(keys.contains(1));
|
||||
assertTrue(keys.contains(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeysWithValueNull() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, null);
|
||||
map.put(2, null);
|
||||
map.put(3, "value");
|
||||
|
||||
List<Integer> keys = map.keysWithValue(null);
|
||||
assertEquals(2, keys.size());
|
||||
assertTrue(keys.contains(1));
|
||||
assertTrue(keys.contains(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeysWithValueNoMatch() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(1, "one");
|
||||
map.put(2, "two");
|
||||
|
||||
List<Integer> keys = map.keysWithValue("nonexistent");
|
||||
assertTrue(keys.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRehashing() {
|
||||
// Use small initial capacity to trigger rehash
|
||||
DynIntHashMap map = new DynIntHashMap(2, 0.75f);
|
||||
|
||||
// Add enough entries to trigger rehash
|
||||
for (int i = 0; i < 100; i++) {
|
||||
map.put(i, "value" + i);
|
||||
}
|
||||
|
||||
assertEquals(100, map.size());
|
||||
|
||||
// Verify all entries are still accessible
|
||||
for (int i = 0; i < 100; i++) {
|
||||
assertEquals("value" + i, map.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeKey() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(-1, "negative");
|
||||
assertEquals("negative", map.get(-1));
|
||||
assertTrue(map.containsKey(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroKey() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(0, "zero");
|
||||
assertEquals("zero", map.get(0));
|
||||
assertTrue(map.containsKey(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIntKey() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(Integer.MAX_VALUE, "max");
|
||||
assertEquals("max", map.get(Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinIntKey() {
|
||||
DynIntHashMap map = new DynIntHashMap();
|
||||
map.put(Integer.MIN_VALUE, "min");
|
||||
assertEquals("min", map.get(Integer.MIN_VALUE));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package org.dynmap.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class IpAddressMatcherTest {
|
||||
|
||||
// IPv4 exact match tests
|
||||
@Test
|
||||
public void testIPv4ExactMatch() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.100");
|
||||
assertTrue(matcher.matches("192.168.1.100"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4ExactMatchNoMatch() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.100");
|
||||
assertFalse(matcher.matches("192.168.1.101"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4Localhost() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("127.0.0.1");
|
||||
assertTrue(matcher.matches("127.0.0.1"));
|
||||
assertFalse(matcher.matches("127.0.0.2"));
|
||||
}
|
||||
|
||||
// IPv4 CIDR tests
|
||||
@Test
|
||||
public void testIPv4Cidr24() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.0/24");
|
||||
assertTrue(matcher.matches("192.168.1.0"));
|
||||
assertTrue(matcher.matches("192.168.1.1"));
|
||||
assertTrue(matcher.matches("192.168.1.255"));
|
||||
assertFalse(matcher.matches("192.168.2.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4Cidr16() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.0.0/16");
|
||||
assertTrue(matcher.matches("192.168.0.1"));
|
||||
assertTrue(matcher.matches("192.168.255.255"));
|
||||
assertFalse(matcher.matches("192.169.0.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4Cidr8() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("10.0.0.0/8");
|
||||
assertTrue(matcher.matches("10.0.0.1"));
|
||||
assertTrue(matcher.matches("10.255.255.255"));
|
||||
assertFalse(matcher.matches("11.0.0.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4Cidr32() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.100/32");
|
||||
assertTrue(matcher.matches("192.168.1.100"));
|
||||
assertFalse(matcher.matches("192.168.1.101"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv4CidrZero() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("0.0.0.0/0");
|
||||
assertTrue(matcher.matches("192.168.1.1"));
|
||||
assertTrue(matcher.matches("10.0.0.1"));
|
||||
assertTrue(matcher.matches("255.255.255.255"));
|
||||
}
|
||||
|
||||
// IPv6 tests
|
||||
@Test
|
||||
public void testIPv6ExactMatch() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("::1");
|
||||
assertTrue(matcher.matches("::1"));
|
||||
assertTrue(matcher.matches("0:0:0:0:0:0:0:1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv6Cidr() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("2001:db8::/32");
|
||||
assertTrue(matcher.matches("2001:db8::1"));
|
||||
assertTrue(matcher.matches("2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"));
|
||||
assertFalse(matcher.matches("2001:db9::1"));
|
||||
}
|
||||
|
||||
// Cross-family rejection tests
|
||||
@Test
|
||||
public void testIPv4DoesNotMatchIPv6() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("192.168.1.0/24");
|
||||
assertFalse(matcher.matches("::1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIPv6DoesNotMatchIPv4() {
|
||||
IpAddressMatcher matcher = new IpAddressMatcher("::1");
|
||||
assertFalse(matcher.matches("127.0.0.1"));
|
||||
}
|
||||
|
||||
// Edge cases
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInvalidIPAddress() {
|
||||
new IpAddressMatcher("invalid.ip.address");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrivateNetworkRanges() {
|
||||
// Class A private
|
||||
IpAddressMatcher classA = new IpAddressMatcher("10.0.0.0/8");
|
||||
assertTrue(classA.matches("10.0.0.1"));
|
||||
assertTrue(classA.matches("10.255.255.254"));
|
||||
|
||||
// Class B private
|
||||
IpAddressMatcher classB = new IpAddressMatcher("172.16.0.0/12");
|
||||
assertTrue(classB.matches("172.16.0.1"));
|
||||
assertTrue(classB.matches("172.31.255.254"));
|
||||
assertFalse(classB.matches("172.32.0.1"));
|
||||
|
||||
// Class C private
|
||||
IpAddressMatcher classC = new IpAddressMatcher("192.168.0.0/16");
|
||||
assertTrue(classC.matches("192.168.0.1"));
|
||||
assertTrue(classC.matches("192.168.255.254"));
|
||||
}
|
||||
}
|
||||
196
DynmapCore/src/test/java/org/dynmap/utils/Matrix3DTest.java
Normal file
196
DynmapCore/src/test/java/org/dynmap/utils/Matrix3DTest.java
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
package org.dynmap.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Matrix3DTest {
|
||||
|
||||
private static final double DELTA = 1e-10;
|
||||
|
||||
@Test
|
||||
public void testIdentityConstructor() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
double[] v = {1.0, 2.0, 3.0};
|
||||
m.transform(v);
|
||||
// Identity matrix should not change the vector
|
||||
assertEquals(1.0, v[0], DELTA);
|
||||
assertEquals(2.0, v[1], DELTA);
|
||||
assertEquals(3.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterizedConstructor() {
|
||||
// Create a matrix that doubles each component
|
||||
Matrix3D m = new Matrix3D(2, 0, 0, 0, 2, 0, 0, 0, 2);
|
||||
double[] v = {1.0, 2.0, 3.0};
|
||||
m.transform(v);
|
||||
assertEquals(2.0, v[0], DELTA);
|
||||
assertEquals(4.0, v[1], DELTA);
|
||||
assertEquals(6.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransformArray() {
|
||||
Matrix3D m = new Matrix3D(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
double[] v = {1.0, 1.0, 1.0};
|
||||
m.transform(v);
|
||||
// Row 1: 1*1 + 2*1 + 3*1 = 6
|
||||
// Row 2: 4*1 + 5*1 + 6*1 = 15
|
||||
// Row 3: 7*1 + 8*1 + 9*1 = 24
|
||||
assertEquals(6.0, v[0], DELTA);
|
||||
assertEquals(15.0, v[1], DELTA);
|
||||
assertEquals(24.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransformVector3D() {
|
||||
Matrix3D m = new Matrix3D(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
Vector3D v = new Vector3D(1.0, 1.0, 1.0);
|
||||
m.transform(v);
|
||||
assertEquals(6.0, v.x, DELTA);
|
||||
assertEquals(15.0, v.y, DELTA);
|
||||
assertEquals(24.0, v.z, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransformVector3DWithOutput() {
|
||||
Matrix3D m = new Matrix3D(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
Vector3D v = new Vector3D(1.0, 1.0, 1.0);
|
||||
Vector3D out = new Vector3D();
|
||||
m.transform(v, out);
|
||||
// Input should be unchanged
|
||||
assertEquals(1.0, v.x, DELTA);
|
||||
assertEquals(1.0, v.y, DELTA);
|
||||
assertEquals(1.0, v.z, DELTA);
|
||||
// Output should have transformed values
|
||||
assertEquals(6.0, out.x, DELTA);
|
||||
assertEquals(15.0, out.y, DELTA);
|
||||
assertEquals(24.0, out.z, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScale() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.scale(2.0, 3.0, 4.0);
|
||||
double[] v = {1.0, 1.0, 1.0};
|
||||
m.transform(v);
|
||||
assertEquals(2.0, v[0], DELTA);
|
||||
assertEquals(3.0, v[1], DELTA);
|
||||
assertEquals(4.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotateXY90Degrees() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.rotateXY(90.0);
|
||||
double[] v = {1.0, 0.0, 0.0};
|
||||
m.transform(v);
|
||||
// X axis rotated 90 degrees clockwise around Z should point to Y
|
||||
assertEquals(0.0, v[0], DELTA);
|
||||
assertEquals(-1.0, v[1], DELTA);
|
||||
assertEquals(0.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotateXZ90Degrees() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.rotateXZ(90.0);
|
||||
double[] v = {1.0, 0.0, 0.0};
|
||||
m.transform(v);
|
||||
// X axis rotated 90 degrees clockwise around Y should point to +Z
|
||||
assertEquals(0.0, v[0], DELTA);
|
||||
assertEquals(0.0, v[1], DELTA);
|
||||
assertEquals(1.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotateYZ90Degrees() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.rotateYZ(90.0);
|
||||
double[] v = {0.0, 1.0, 0.0};
|
||||
m.transform(v);
|
||||
// Y axis rotated 90 degrees clockwise around X should point to Z
|
||||
assertEquals(0.0, v[0], DELTA);
|
||||
assertEquals(0.0, v[1], DELTA);
|
||||
assertEquals(-1.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotate360DegreesReturnsToOriginal() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.rotateXY(360.0);
|
||||
double[] v = {1.0, 2.0, 3.0};
|
||||
m.transform(v);
|
||||
assertEquals(1.0, v[0], DELTA);
|
||||
assertEquals(2.0, v[1], DELTA);
|
||||
assertEquals(3.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiply() {
|
||||
// Create two scaling matrices
|
||||
Matrix3D m1 = new Matrix3D(2, 0, 0, 0, 2, 0, 0, 0, 2);
|
||||
Matrix3D m2 = new Matrix3D(3, 0, 0, 0, 3, 0, 0, 0, 3);
|
||||
m1.multiply(m2);
|
||||
double[] v = {1.0, 1.0, 1.0};
|
||||
m1.transform(v);
|
||||
// Should scale by 6 (2*3)
|
||||
assertEquals(6.0, v[0], DELTA);
|
||||
assertEquals(6.0, v[1], DELTA);
|
||||
assertEquals(6.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShearZ() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.shearZ(1.0, 0.0);
|
||||
// With shearZ matrix [1,0,0; 0,1,0; x_fact,y_fact,1] multiplied as mat*this
|
||||
// The result matrix has x_fact in position m31
|
||||
// transform: v1 = m11*x + m12*y + m13*z = x
|
||||
// v2 = m21*x + m22*y + m23*z = y
|
||||
// v3 = m31*x + m32*y + m33*z = x_fact*x + y_fact*y + z
|
||||
double[] v = {1.0, 0.0, 0.0};
|
||||
m.transform(v);
|
||||
// X contributes to Z via shear
|
||||
assertEquals(1.0, v[0], DELTA);
|
||||
assertEquals(0.0, v[1], DELTA);
|
||||
assertEquals(1.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChainedTransformations() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
m.scale(2.0, 2.0, 2.0);
|
||||
m.rotateXY(90.0);
|
||||
double[] v = {1.0, 0.0, 0.0};
|
||||
m.transform(v);
|
||||
// First scale by 2, then rotate - result should be scaled and rotated
|
||||
assertEquals(0.0, v[0], DELTA);
|
||||
assertEquals(-2.0, v[1], DELTA);
|
||||
assertEquals(0.0, v[2], DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
Matrix3D m = new Matrix3D();
|
||||
String str = m.toString();
|
||||
assertNotNull(str);
|
||||
assertTrue(str.contains("1.0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSON() {
|
||||
Matrix3D m = new Matrix3D(1, 2, 3, 4, 5, 6, 7, 8, 9);
|
||||
org.json.simple.JSONArray json = m.toJSON();
|
||||
assertEquals(9, json.size());
|
||||
assertEquals(1.0, json.get(0));
|
||||
assertEquals(2.0, json.get(1));
|
||||
assertEquals(3.0, json.get(2));
|
||||
assertEquals(4.0, json.get(3));
|
||||
assertEquals(5.0, json.get(4));
|
||||
assertEquals(6.0, json.get(5));
|
||||
assertEquals(7.0, json.get(6));
|
||||
assertEquals(8.0, json.get(7));
|
||||
assertEquals(9.0, json.get(8));
|
||||
}
|
||||
}
|
||||
173
DynmapCore/src/test/java/org/dynmap/utils/Vector3DTest.java
Normal file
173
DynmapCore/src/test/java/org/dynmap/utils/Vector3DTest.java
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package org.dynmap.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Vector3DTest {
|
||||
|
||||
private static final double DELTA = 1e-10;
|
||||
|
||||
@Test
|
||||
public void testDefaultConstructor() {
|
||||
Vector3D v = new Vector3D();
|
||||
assertEquals(0.0, v.x, DELTA);
|
||||
assertEquals(0.0, v.y, DELTA);
|
||||
assertEquals(0.0, v.z, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterizedConstructor() {
|
||||
Vector3D v = new Vector3D(1.0, 2.0, 3.0);
|
||||
assertEquals(1.0, v.x, DELTA);
|
||||
assertEquals(2.0, v.y, DELTA);
|
||||
assertEquals(3.0, v.z, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyConstructor() {
|
||||
Vector3D original = new Vector3D(5.0, 6.0, 7.0);
|
||||
Vector3D copy = new Vector3D(original);
|
||||
assertEquals(original.x, copy.x, DELTA);
|
||||
assertEquals(original.y, copy.y, DELTA);
|
||||
assertEquals(original.z, copy.z, DELTA);
|
||||
// Ensure it's a copy, not a reference
|
||||
original.x = 100.0;
|
||||
assertEquals(5.0, copy.x, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSet() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D();
|
||||
Vector3D result = v2.set(v1);
|
||||
assertEquals(1.0, v2.x, DELTA);
|
||||
assertEquals(2.0, v2.y, DELTA);
|
||||
assertEquals(3.0, v2.z, DELTA);
|
||||
assertSame(v2, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D(4.0, 5.0, 6.0);
|
||||
Vector3D result = v1.add(v2);
|
||||
assertEquals(5.0, v1.x, DELTA);
|
||||
assertEquals(7.0, v1.y, DELTA);
|
||||
assertEquals(9.0, v1.z, DELTA);
|
||||
assertSame(v1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtract() {
|
||||
Vector3D v1 = new Vector3D(5.0, 7.0, 9.0);
|
||||
Vector3D v2 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D result = v1.subtract(v2);
|
||||
assertEquals(4.0, v1.x, DELTA);
|
||||
assertEquals(5.0, v1.y, DELTA);
|
||||
assertEquals(6.0, v1.z, DELTA);
|
||||
assertSame(v1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScale() {
|
||||
Vector3D v = new Vector3D(2.0, 3.0, 4.0);
|
||||
Vector3D result = v.scale(2.0);
|
||||
assertEquals(4.0, v.x, DELTA);
|
||||
assertEquals(6.0, v.y, DELTA);
|
||||
assertEquals(8.0, v.z, DELTA);
|
||||
assertSame(v, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInnerProduct() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D(4.0, 5.0, 6.0);
|
||||
double result = v1.innerProduct(v2);
|
||||
// 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
|
||||
assertEquals(32.0, result, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrossProduct() {
|
||||
Vector3D v1 = new Vector3D(1.0, 0.0, 0.0);
|
||||
Vector3D v2 = new Vector3D(0.0, 1.0, 0.0);
|
||||
Vector3D result = v1.crossProduct(v2);
|
||||
// i x j = k
|
||||
assertEquals(0.0, v1.x, DELTA);
|
||||
assertEquals(0.0, v1.y, DELTA);
|
||||
assertEquals(1.0, v1.z, DELTA);
|
||||
assertSame(v1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrossProductGeneral() {
|
||||
Vector3D v1 = new Vector3D(2.0, 3.0, 4.0);
|
||||
Vector3D v2 = new Vector3D(5.0, 6.0, 7.0);
|
||||
v1.crossProduct(v2);
|
||||
// (3*7 - 4*6, 4*5 - 2*7, 2*6 - 3*5) = (21-24, 20-14, 12-15) = (-3, 6, -3)
|
||||
assertEquals(-3.0, v1.x, DELTA);
|
||||
assertEquals(6.0, v1.y, DELTA);
|
||||
assertEquals(-3.0, v1.z, DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLength() {
|
||||
Vector3D v = new Vector3D(3.0, 4.0, 0.0);
|
||||
assertEquals(5.0, v.length(), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLengthUnit() {
|
||||
Vector3D v = new Vector3D(1.0, 0.0, 0.0);
|
||||
assertEquals(1.0, v.length(), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLengthZero() {
|
||||
Vector3D v = new Vector3D();
|
||||
assertEquals(0.0, v.length(), DELTA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D(1.0, 2.0, 3.0);
|
||||
assertTrue(v1.equals(v2));
|
||||
assertTrue(v2.equals(v1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsNotEqual() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D(1.0, 2.0, 4.0);
|
||||
assertFalse(v1.equals(v2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsNull() {
|
||||
Vector3D v = new Vector3D(1.0, 2.0, 3.0);
|
||||
assertFalse(v.equals(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsWrongType() {
|
||||
Vector3D v = new Vector3D(1.0, 2.0, 3.0);
|
||||
assertFalse(v.equals("not a vector"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCodeConsistency() {
|
||||
Vector3D v1 = new Vector3D(1.0, 2.0, 3.0);
|
||||
Vector3D v2 = new Vector3D(1.0, 2.0, 3.0);
|
||||
assertEquals(v1.hashCode(), v2.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
Vector3D v = new Vector3D(1.0, 2.0, 3.0);
|
||||
String str = v.toString();
|
||||
assertTrue(str.contains("1.0"));
|
||||
assertTrue(str.contains("2.0"));
|
||||
assertTrue(str.contains("3.0"));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue