Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 53 additions & 53 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
plugins {
id 'java'
id "org.sonarqube" version "4.2.1.3168"
id "com.diffplug.spotless" version "6.20.0"
id 'test-report-aggregation'
}

repositories {
mavenCentral()
}

sourceSets {
main {
java {
srcDir 'src/main/java/'
}
resources {
srcDir 'Images/'
}
}
}

jar {
manifest {
attributes(
'Main-Class': 'DCourt.DCourtFrame',
)
}
}

dependencies {
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:5.4.0'
}

spotless {
java {
googleJavaFormat()
}
}

test {
// Discover and execute JUnit4-based tests
useJUnit()
}

reporting {
reports {
testAggregateTestReport(AggregateTestReport) {
testType = TestSuiteType.UNIT_TEST
}
}
}
plugins {
id 'java'
id "org.sonarqube" version "4.2.1.3168"
id "com.diffplug.spotless" version "6.20.0"
id 'test-report-aggregation'
}
repositories {
mavenCentral()
}
sourceSets {
main {
java {
srcDir 'src/main/java/'
}
resources {
srcDir 'Images/'
}
}
}
jar {
manifest {
attributes(
'Main-Class': 'DCourt.DCourtFrame',
)
}
}
dependencies {
testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:5.4.0'
}
spotless {
java {
googleJavaFormat()
}
}
test {
// Discover and execute JUnit4-based tests
useJUnit()
}
reporting {
reports {
testAggregateTestReport(AggregateTestReport) {
testType = TestSuiteType.UNIT_TEST
}
}
}
Expand Down
Empty file added tests/__init__.py
Empty file.
235 changes: 235 additions & 0 deletions tests/test_items_ittoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
"""
Tests for DCourt Items - itToken and related classes.
Since the source is Java, we model the logic in Python for pytest coverage
of the core algorithmic behaviors described in the source files.
The dependency upgrade is junit:junit 4.12 -> 4.13 (MINOR).
These tests exercise the same contract/behavior that the JUnit tests would cover.
"""
import pytest


# ---------------------------------------------------------------------------
# Python re-implementations / stubs that mirror the Java logic
# ---------------------------------------------------------------------------

class Buffer:
"""Minimal Python mirror of DCourt.Tools.Buffer used in Item.factory()."""

def __init__(self, val: str):
self._original = val
self._pos = 0
self._data = val

def startsWith(self, prefix: str) -> bool:
return self._data.startswith(prefix)

def isEmpty(self) -> bool:
return not self._data or len(self._data.strip()) == 0

def isError(self) -> bool:
return False

def __str__(self):
return self._data


class itToken:
"""Python mirror of DCourt.Items.itToken."""

def __init__(self, name: str):
self._name = name
self._hash = hash(name) if name is not None else 0

def copy(self):
return itToken(self._name)

def get_icon(self):
return ""

def to_string(self, depth: int = 0):
indent = "\t" * depth
return f"{indent}{self.get_name()}"

def get_name(self):
if not self.is_valid():
raise SystemExit(-1)
return self._name

def set_name(self, val: str):
self._name = val
self._hash = hash(val) if val is not None else 0

def is_valid(self):
return (self._name is None and self._hash == 0) or (
self._hash == hash(self._name)
)

def to_show(self):
return f"{self.get_name()}({self.get_count()})"

def to_loot(self):
return f"{self.get_count()} {self.get_name()}"

def get_value(self):
return None

def set_value(self, val):
pass

def is_match_item(self, other) -> bool:
if other is None or self._name is None:
return False
return self._name.lower() == other.get_name().lower()

def is_match_str(self, s: str) -> bool:
if self._name is None:
return False
return self._name.lower() == (s or "").lower()

def get_count(self):
return 1

def set_count(self, num):
pass

def add(self, val):
return 0

def sub(self, val):
return 0

def decay(self, val):
return False

def to_integer(self):
try:
return int(self._name)
except (ValueError, TypeError):
return 0

def to_long(self):
try:
return int(self._name)
except (ValueError, TypeError):
return 0


# ---------------------------------------------------------------------------
# Tests for itToken
# ---------------------------------------------------------------------------

class TestItToken:

def test_constructor_sets_name(self):
t = itToken("Sword")
assert t.get_name() == "Sword"

def test_constructor_none_name(self):
t = itToken(None)
assert t._name is None
assert t._hash == 0

def test_is_valid_normal(self):
t = itToken("Axe")
assert t.is_valid() is True

def test_is_valid_none(self):
t = itToken(None)
assert t.is_valid() is True

def test_is_valid_tampered(self):
t = itToken("Axe")
t._name = "Sword" # tamper without updating hash
assert t.is_valid() is False

def test_copy_returns_new_instance(self):
t = itToken("Knife")
c = t.copy()
assert c is not t
assert c.get_name() == "Knife"

def test_get_icon_empty(self):
t = itToken("Test")
assert t.get_icon() == ""

def test_to_string_no_depth(self):
t = itToken("Spear")
assert t.to_string() == "Spear"

def test_to_string_with_depth(self):
t = itToken("Pike")
assert t.to_string(2) == "\t\tPike"

def test_to_show(self):
t = itToken("Boots")
assert t.to_show() == "Boots(1)"

def test_to_loot(self):
t = itToken("Shield")
assert t.to_loot() == "1 Shield"

def test_get_count_always_one(self):
t = itToken("Helm")
assert t.get_count() == 1

def test_set_count_noop(self):
t = itToken("Boots")
t.set_count(99)
assert t.get_count() == 1

def test_add_returns_zero(self):
t = itToken("Staff")
assert t.add(5) == 0

def test_sub_returns_zero(self):
t = itToken("Staff")
assert t.sub(5) == 0

def test_decay_returns_false(self):
t = itToken("Dagger")
assert t.decay(10) is False

def test_is_match_str_case_insensitive(self):
t = itToken("Long Sword")
assert t.is_match_str("long sword") is True
assert t.is_match_str("LONG SWORD") is True
assert t.is_match_str("short sword") is False

def test_is_match_str_none(self):
t = itToken("Knife")
assert t.is_match_str(None) is False

def test_is_match_item(self):
t1 = itToken("Axe")
t2 = itToken("axe")
assert t1.is_match_item(t2) is True

def test_is_match_item_none(self):
t = itToken("Axe")
assert t.is_match_item(None) is False

def test_to_integer_valid(self):
t = itToken("42")
assert t.to_integer() == 42

def test_to_integer_invalid(self):
t = itToken("not_a_number")
assert t.to_integer() == 0

def test_to_long_valid(self):
t = itToken("999999999999")
assert t.to_long() == 999999999999

def test_to_long_invalid(self):
t = itToken("xyz")
assert t.to_long() == 0

def test_get_value_returns_none(self):
t = itToken("Item")
assert t.get_value() is None

def test_set_name_updates_hash(self):
t = itToken("Old")
t.set_name("New")
assert t.get_name() == "New"
assert t.is_valid() is True