Skip to content

Commit 40881f9

Browse files
authored
Merge pull request #6 from paulorb/unittests
Unittests
2 parents c4d4037 + a57524d commit 40881f9

File tree

12 files changed

+132
-10
lines changed

12 files changed

+132
-10
lines changed

.github/badges/branches.svg

Lines changed: 1 addition & 0 deletions
Loading

.github/badges/jacoco.svg

Lines changed: 1 addition & 0 deletions
Loading

.github/workflows/main.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ jobs:
3131
run: |
3232
./gradlew test jacocoTestReport
3333
34+
- name: Generate JaCoCo Badge
35+
uses: cicirello/jacoco-badge-generator@v2
36+
with:
37+
generate-branches-badge: true
38+
jacoco-csv-file: build/reports/jacoco/test/jacocoTestReport.csv
39+
40+
- name: Commit and push the badge (if it changed)
41+
uses: EndBug/add-and-commit@v7
42+
with:
43+
default_author: github_actions
44+
message: 'commit badge'
45+
add: '*.svg'
46+
3447
- name: Upload Artifacts
3548
uses: actions/upload-artifact@v2
3649
with:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=paulorb_modbus-simulator-cli&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=paulorb_modbus-simulator-cli)
55
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=paulorb_modbus-simulator-cli&metric=bugs)](https://sonarcloud.io/summary/new_code?id=paulorb_modbus-simulator-cli)
66
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=paulorb_modbus-simulator-cli&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=paulorb_modbus-simulator-cli)
7+
![Coverage](.github/badges/jacoco.svg)
78

89
Modbus simulator CLI is a high-performance modbus TCP server with customizable simulation
910

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ kotlin {
6565
tasks.jacocoTestReport {
6666
reports {
6767
xml.required.set(true)
68+
csv.required.set(true)
6869
}
6970
}
7071

src/main/kotlin/ConfigurationParser.kt

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import org.slf4j.LoggerFactory
12
import java.io.BufferedReader
23
import java.io.File
34
import java.io.StringReader
@@ -9,8 +10,13 @@ class ConfigurationParser {
910

1011
companion object {
1112
var fileName: String = ""
13+
var readFromResources: Boolean = false
14+
val logger = LoggerFactory.getLogger("ConfigurationParser")
1215
}
1316

17+
fun setReadFromResources(value: Boolean) {
18+
readFromResources = value
19+
}
1420

1521
fun setFileName(file: String) {
1622
fileName = file
@@ -19,16 +25,23 @@ class ConfigurationParser {
1925
try {
2026
val context = JAXBContext.newInstance(Device::class.java, Set::class.java, Random::class.java, Delay::class.java, Linear::class.java, Add::class.java, Sub::class.java, Csv::class.java, IfEqual::class.java, Parameters::class.java, Parameter::class.java)
2127
val unmarshaller = context.createUnmarshaller()
22-
if(fileName.isEmpty()) {
28+
return if(fileName.isEmpty() ) {
2329
val reader = StringReader(this::class.java.classLoader.getResource("configuration.xml")!!.readText())
2430
val device = unmarshaller.unmarshal(reader) as Device
25-
return device
26-
}else{
27-
val bufferedReader: BufferedReader = File(fileName).bufferedReader()
28-
val device = unmarshaller.unmarshal(bufferedReader) as Device
29-
return device
31+
device
32+
}else {
33+
if(readFromResources) {
34+
val reader = StringReader(this::class.java.classLoader.getResource(fileName)!!.readText())
35+
val device = unmarshaller.unmarshal(reader) as Device
36+
device
37+
}else {
38+
val bufferedReader: BufferedReader = File(fileName).bufferedReader()
39+
val device = unmarshaller.unmarshal(bufferedReader) as Device
40+
device
41+
}
3042
}
3143
} catch (e: JAXBException) {
44+
logger.error(e.message)
3245
e.printStackTrace()
3346
}
3447
return null

src/main/kotlin/PlcMemory.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class PlcMemory(configurationParser: ConfigurationParser) : IModbusServerEventL
8585
val listCoils = mutableListOf<Boolean>()
8686
for(i in startAddress until startAddress + numberOfRegisters) {
8787
if(coils[i] != null){
88-
listCoils.add(coils[i]!!)
88+
listCoils.add(coils.getValue(i))
8989
}else{
9090
listCoils.add(false)
9191
}
@@ -100,7 +100,7 @@ class PlcMemory(configurationParser: ConfigurationParser) : IModbusServerEventL
100100
for(i in startAddress until startAddress + numberOfRegisters) {
101101
if(holdingRegister[i] != null){
102102
logger.debug("readHoldingRegister address $i value=${holdingRegister[i]}")
103-
listHoldingRegisters.add(holdingRegister[i]!!)
103+
listHoldingRegisters.add(holdingRegister.getValue(i))
104104
}else{
105105
logger.debug("readHoldingRegister address $i value=0")
106106
listHoldingRegisters.add(0)
@@ -115,7 +115,7 @@ class PlcMemory(configurationParser: ConfigurationParser) : IModbusServerEventL
115115
val listInputRegisters = mutableListOf<Short>()
116116
for(i in startAddress until startAddress + numberOfRegisters) {
117117
if(inputRegister[i] != null){
118-
listInputRegisters.add(inputRegister[i]!!)
118+
listInputRegisters.add(inputRegister.getValue(i))
119119
}else{
120120
listInputRegisters.add(0)
121121
}
@@ -129,7 +129,7 @@ class PlcMemory(configurationParser: ConfigurationParser) : IModbusServerEventL
129129
val listCoils = mutableListOf<Boolean>()
130130
for(i in startAddress until startAddress + numberOfRegisters) {
131131
if(inputStatus[i] != null){
132-
listCoils.add(inputStatus[i]!!)
132+
listCoils.add(inputStatus.getValue(i))
133133
}else{
134134
listCoils.add(false)
135135
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import org.junit.jupiter.api.Test
2+
import org.junit.jupiter.api.assertThrows
3+
4+
class ConfigurationParserTest {
5+
6+
// When parser fails to load the xml due to missing device root section the following error will be printed followed by the stacktrace
7+
// 2024-07-23 21:21:04 ERROR ConfigurationParser - unexpected element (uri:"", local:"simulation"). Expected elements are <{}add>,<{}csv>,<{}delay>,<{}device>,<{}ifEqual>,<{}linear>,<{}random>,<{}set>,<{}sub>
8+
@Test
9+
fun `Parser must fail if device section is not present`() {
10+
val configuration = ConfigurationParser()
11+
configuration.setReadFromResources(true)
12+
configuration.setFileName("invalid_missing_device.xml")
13+
assertThrows<NullPointerException> { configuration.getConfiguredDevice() }
14+
}
15+
}

src/test/kotlin/EnvironmentVariablesTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ internal class EnvironmentVariablesTest {
55
@Test
66
fun `Command line parameter must match with parameters definition`() {
77
val configuration = ConfigurationParser()
8+
configuration.setFileName("configuration.xml")
9+
configuration.setReadFromResources(true)
810
val listParameters = mutableListOf<EnvParameter>()
911
listParameters.add(EnvParameter(
1012
"PARAM_INT16",

src/test/kotlin/PlcMemoryTest.kt

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import org.junit.jupiter.api.Test
2+
import org.junit.jupiter.api.assertThrows
3+
import kotlin.test.assertEquals
4+
5+
class PlcMemoryTest {
6+
7+
@Test
8+
fun `PlcMemory must be initialized with configured holding registers symbols`() {
9+
val configuration = ConfigurationParser()
10+
configuration.setReadFromResources(true)
11+
configuration.setFileName("configuration_init.xml")
12+
val plcMemory = PlcMemory(configuration)
13+
val values = plcMemory.readHoldingRegister(14, 1)
14+
assertEquals(1, values.size, )
15+
assertEquals( values[0], 500)
16+
}
17+
18+
@Test
19+
fun `PlcMemory must be initialized with configured input registers symbols`() {
20+
val configuration = ConfigurationParser()
21+
configuration.setReadFromResources(true)
22+
configuration.setFileName("configuration_init.xml")
23+
val plcMemory = PlcMemory(configuration)
24+
val values = plcMemory.readInputRegister(5, 1)
25+
assertEquals(1, values.size, )
26+
assertEquals( values[0], 30)
27+
}
28+
29+
30+
@Test
31+
fun `PlcMemory must be initialized with configured coil registers symbols`() {
32+
val configuration = ConfigurationParser()
33+
configuration.setReadFromResources(true)
34+
configuration.setFileName("configuration_init.xml")
35+
val plcMemory = PlcMemory(configuration)
36+
val values = plcMemory.readCoilStatus(5, 1)
37+
assertEquals(1, values.size)
38+
assertEquals( values[0], true)
39+
}
40+
41+
@Test
42+
fun `PlcMemory must be initialized with configured input status registers symbols`() {
43+
val configuration = ConfigurationParser()
44+
configuration.setReadFromResources(true)
45+
configuration.setFileName("configuration_init.xml")
46+
val plcMemory = PlcMemory(configuration)
47+
val values = plcMemory.readInputStatus(5, 1)
48+
assertEquals(1, values.size)
49+
assertEquals( values[0], true)
50+
}
51+
}

0 commit comments

Comments
 (0)