diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..3624e61fa2 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,53 @@ +name: Build and Test + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + container: + image: eclipse-temurin:17-jdk + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Ant + run: | + apt-get update + apt-get install -y ant + + - name: Show versions + run: | + java -version + ant -version + + - name: Build and test + run: ant all + + - name: Upload jars + uses: actions/upload-artifact@v4 + with: + name: opendis7-jars + path: dist/*.jar + retention-days: 30 + + - name: Upload javadoc + uses: actions/upload-artifact@v4 + with: + name: opendis7-javadoc + path: dist/javadoc/ + retention-days: 30 + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: build/test/results/ + retention-days: 14 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000..1f91e32a80 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,55 @@ +name: Publish Release + +on: + release: + types: [published] + workflow_dispatch: + +jobs: + build-and-release: + runs-on: ubuntu-latest + container: + image: eclipse-temurin:17-jdk + + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Ant and tools + run: | + apt-get update + apt-get install -y ant zip + + - name: Build + run: ant all + + - name: Create release bundle + run: | + mkdir -p release + cp dist/opendis7-*.jar release/ + cp dist/license.txt release/ + cp dist/license.html release/ + cd release && zip -r ../opendis7-release.zip . + + - name: Upload release assets + if: github.event_name == 'release' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + apt-get install -y gh + for jar in dist/opendis7-*.jar; do + gh release upload "${{ github.event.release.tag_name }}" "$jar" --clobber + done + gh release upload "${{ github.event.release.tag_name }}" opendis7-release.zip --clobber + + - name: Upload artifacts + if: github.event_name == 'workflow_dispatch' + uses: actions/upload-artifact@v4 + with: + name: opendis7-release + path: | + dist/opendis7-*.jar + opendis7-release.zip diff --git a/.gitignore b/.gitignore index 9cf6af8978..38289154d0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /pduLog/Pdusave.dislog .DS_Store /nbproject/genfiles.properties +PDU_TESTING.md diff --git a/build.xml b/build.xml index 2f2b0c521b..0ee064dce8 100644 --- a/build.xml +++ b/build.xml @@ -179,22 +179,16 @@ POSSIBILITY OF SUCH DAMAGE. - + - - - - + + - - - - - - - + + + diff --git a/test/edu/nps/moves/dis7/test/AcknowledgePduTest.java b/test/edu/nps/moves/dis7/test/AcknowledgePduTest.java new file mode 100644 index 0000000000..b99f484615 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AcknowledgePduTest.java @@ -0,0 +1,114 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.AcknowledgeAcknowledgeFlag; +import edu.nps.moves.dis7.enumerations.AcknowledgeResponseFlag; +import edu.nps.moves.dis7.pdus.AcknowledgePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Acknowledge PDU fields and values. + */ +@DisplayName("AcknowledgePduTest") +public class AcknowledgePduTest extends PduTest +{ + /** default constructor */ + public AcknowledgePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** AcknowledgePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** AcknowledgePduTest testMultiplePdus()"); + + AcknowledgePdu acknowledgePdu = pduFactory.makeAcknowledgePdu(); + + acknowledgePdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + acknowledgePdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + acknowledgePdu.setAcknowledgeFlag(AcknowledgeAcknowledgeFlag.CREATE_ENTITY); + acknowledgePdu.setResponseFlag(AcknowledgeResponseFlag.ABLE_TO_COMPLY); + acknowledgePdu.setRequestID(5001); + testOnePdu(acknowledgePdu); + + acknowledgePdu.setRequestID(5002); + acknowledgePdu.setAcknowledgeFlag(AcknowledgeAcknowledgeFlag.REMOVE_ENTITY); + testOnePdu(acknowledgePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + AcknowledgePdu createdCast = (AcknowledgePdu) createdPdu; + AcknowledgePdu receivedCast = (AcknowledgePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getAcknowledgeFlag(), receivedCast.getAcknowledgeFlag(), "mismatched AcknowledgeFlag"); + assertEquals(createdCast.getResponseFlag(), receivedCast.getResponseFlag(), "mismatched ResponseFlag"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new AcknowledgePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/AcknowledgeReliablePduTest.java b/test/edu/nps/moves/dis7/test/AcknowledgeReliablePduTest.java new file mode 100644 index 0000000000..92f6fabd87 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AcknowledgeReliablePduTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.AcknowledgeAcknowledgeFlag; +import edu.nps.moves.dis7.enumerations.AcknowledgeResponseFlag; +import edu.nps.moves.dis7.pdus.AcknowledgeReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Acknowledge Reliable PDU fields and values. + */ +@DisplayName("AcknowledgeReliablePduTest") +public class AcknowledgeReliablePduTest extends PduTest +{ + /** default constructor */ + public AcknowledgeReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** AcknowledgeReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** AcknowledgeReliablePduTest testMultiplePdus()"); + + AcknowledgeReliablePdu arPdu = pduFactory.makeAcknowledgeReliablePdu(); + + arPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + arPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + arPdu.setAcknowledgeFlag(AcknowledgeAcknowledgeFlag.CREATE_ENTITY); + arPdu.setResponseFlag(AcknowledgeResponseFlag.ABLE_TO_COMPLY); + arPdu.setRequestID(501); + testOnePdu(arPdu); + + arPdu.setAcknowledgeFlag(AcknowledgeAcknowledgeFlag.REMOVE_ENTITY); + arPdu.setResponseFlag(AcknowledgeResponseFlag.UNABLE_TO_COMPLY); + arPdu.setRequestID(502); + testOnePdu(arPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + AcknowledgeReliablePdu createdCast = (AcknowledgeReliablePdu) createdPdu; + AcknowledgeReliablePdu receivedCast = (AcknowledgeReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getAcknowledgeFlag(), receivedCast.getAcknowledgeFlag(), "mismatched AcknowledgeFlag"); + assertEquals(createdCast.getResponseFlag(), receivedCast.getResponseFlag(), "mismatched ResponseFlag"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new AcknowledgeReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ActionRequestPduTest.java b/test/edu/nps/moves/dis7/test/ActionRequestPduTest.java new file mode 100644 index 0000000000..ef97218c62 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ActionRequestPduTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ActionRequestPdu; +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import edu.nps.moves.dis7.enumerations.VariableRecordType; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Action Request PDU fields and values. + */ +@DisplayName("ActionRequestPduTest") +public class ActionRequestPduTest extends PduTest +{ + /** default constructor */ + public ActionRequestPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ActionRequestPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ActionRequestPduTest testMultiplePdus()"); + + ActionRequestPdu actionRequestPdu = pduFactory.makeActionRequestPdu(); + + actionRequestPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + actionRequestPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + actionRequestPdu.setRequestID(6001); + actionRequestPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(42)); + actionRequestPdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST).setVariableDatumValue(new byte[]{1, 2, 3, 4, 5, 6, 7, 8})); + testOnePdu(actionRequestPdu); + + actionRequestPdu.setRequestID(6002); + testOnePdu(actionRequestPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ActionRequestPdu createdCast = (ActionRequestPdu) createdPdu; + ActionRequestPdu receivedCast = (ActionRequestPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getActionID(), receivedCast.getActionID(), "mismatched ActionID"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ActionRequestPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ActionRequestReliablePduTest.java b/test/edu/nps/moves/dis7/test/ActionRequestReliablePduTest.java new file mode 100644 index 0000000000..72619d135d --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ActionRequestReliablePduTest.java @@ -0,0 +1,116 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ActionRequestActionID; +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.ActionRequestReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Action Request Reliable PDU fields and values. + */ +@DisplayName("ActionRequestReliablePduTest") +public class ActionRequestReliablePduTest extends PduTest +{ + /** default constructor */ + public ActionRequestReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ActionRequestReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ActionRequestReliablePduTest testMultiplePdus()"); + + ActionRequestReliablePdu arrPdu = pduFactory.makeActionRequestReliablePdu(); + + arrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + arrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + arrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + arrPdu.setRequestID(601); + arrPdu.setActionID(ActionRequestActionID.OTHER); + testOnePdu(arrPdu); + + arrPdu.setRequestID(602); + arrPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + testOnePdu(arrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ActionRequestReliablePdu createdCast = (ActionRequestReliablePdu) createdPdu; + ActionRequestReliablePdu receivedCast = (ActionRequestReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getActionID(), receivedCast.getActionID(), "mismatched ActionID"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ActionRequestReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ActionResponsePduTest.java b/test/edu/nps/moves/dis7/test/ActionResponsePduTest.java new file mode 100644 index 0000000000..3febf7457f --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ActionResponsePduTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ActionResponsePdu; +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import edu.nps.moves.dis7.enumerations.VariableRecordType; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Action Response PDU fields and values. + */ +@DisplayName("ActionResponsePduTest") +public class ActionResponsePduTest extends PduTest +{ + /** default constructor */ + public ActionResponsePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ActionResponsePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ActionResponsePduTest testMultiplePdus()"); + + ActionResponsePdu actionResponsePdu = pduFactory.makeActionResponsePdu(); + + actionResponsePdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + actionResponsePdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + actionResponsePdu.setRequestID(7001); + actionResponsePdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(99)); + actionResponsePdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST).setVariableDatumValue(new byte[]{10, 20, 30, 40, 50, 60, 70, 80})); + testOnePdu(actionResponsePdu); + + actionResponsePdu.setRequestID(7002); + testOnePdu(actionResponsePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ActionResponsePdu createdCast = (ActionResponsePdu) createdPdu; + ActionResponsePdu receivedCast = (ActionResponsePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequestStatus(), receivedCast.getRequestStatus(), "mismatched RequestStatus"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ActionResponsePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ActionResponseReliablePduTest.java b/test/edu/nps/moves/dis7/test/ActionResponseReliablePduTest.java new file mode 100644 index 0000000000..79679d2bdc --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ActionResponseReliablePduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ActionResponseRequestStatus; +import edu.nps.moves.dis7.pdus.ActionResponseReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Action Response Reliable PDU fields and values. + */ +@DisplayName("ActionResponseReliablePduTest") +public class ActionResponseReliablePduTest extends PduTest +{ + /** default constructor */ + public ActionResponseReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ActionResponseReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ActionResponseReliablePduTest testMultiplePdus()"); + + ActionResponseReliablePdu arrPdu = pduFactory.makeActionResponseReliablePdu(); + + arrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + arrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + arrPdu.setRequestID(701); + arrPdu.setResponseStatus(ActionResponseRequestStatus.OTHER); + testOnePdu(arrPdu); + + arrPdu.setRequestID(702); + arrPdu.setResponseStatus(ActionResponseRequestStatus.PENDING); + testOnePdu(arrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ActionResponseReliablePdu createdCast = (ActionResponseReliablePdu) createdPdu; + ActionResponseReliablePdu receivedCast = (ActionResponseReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getResponseStatus(), receivedCast.getResponseStatus(), "mismatched ResponseStatus"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ActionResponseReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/AggregateStatePduTest.java b/test/edu/nps/moves/dis7/test/AggregateStatePduTest.java new file mode 100644 index 0000000000..9516282055 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AggregateStatePduTest.java @@ -0,0 +1,136 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.AggregateStateAggregateState; +import edu.nps.moves.dis7.enumerations.AggregateStateFormation; +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.AggregateIdentifier; +import edu.nps.moves.dis7.pdus.AggregateMarking; +import edu.nps.moves.dis7.pdus.AggregateStatePdu; +import edu.nps.moves.dis7.pdus.AggregateType; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; +import edu.nps.moves.dis7.enumerations.AggregateStateAggregateKind; + +/** + * Unit tests for satisfactory handling of Aggregate State PDU fields and values. + */ +@DisplayName("AggregateStatePduTest") +public class AggregateStatePduTest extends PduTest +{ + /** default constructor */ + public AggregateStatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** AggregateStatePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** AggregateStatePduTest testMultiplePdus()"); + + AggregateStatePdu asPdu = pduFactory.makeAggregateStatePdu(); + + asPdu.setAggregateID(new AggregateIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setAggregateID(100)); + asPdu.setForceID(ForceID.FRIENDLY); + asPdu.setAggregateState(AggregateStateAggregateState.AGGREGATED); + asPdu.setAggregateType(new AggregateType().setAggregateKind(AggregateStateAggregateKind.MILITARY_HIERARCHY).setDomain(PlatformDomain.LAND).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + asPdu.setFormation(AggregateStateFormation.VEE); + asPdu.setAggregateMarking(new AggregateMarking().setCharacters("TestAgg1".getBytes())); + asPdu.setDimensions(new Vector3Float().setX(100.0f).setY(200.0f).setZ(50.0f)); + asPdu.setCenterOfMass(new Vector3Double().setX(1000.0).setY(2000.0).setZ(3000.0)); + asPdu.setVelocity(new Vector3Float().setX(10.0f).setY(5.0f).setZ(0.0f)); + testOnePdu(asPdu); + + asPdu.setAggregateState(AggregateStateAggregateState.DISAGGREGATED); + asPdu.setFormation(AggregateStateFormation.ASSEMBLY); + testOnePdu(asPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + AggregateStatePdu createdCast = (AggregateStatePdu) createdPdu; + AggregateStatePdu receivedCast = (AggregateStatePdu) receivedPdus.get(0); + + assertEquals(createdCast.getAggregateID(), receivedCast.getAggregateID(), "mismatched AggregateID"); + assertEquals(createdCast.getForceID(), receivedCast.getForceID(), "mismatched ForceID"); + assertEquals(createdCast.getAggregateState(), receivedCast.getAggregateState(), "mismatched AggregateState"); + assertEquals(createdCast.getAggregateType(), receivedCast.getAggregateType(), "mismatched AggregateType"); + assertEquals(createdCast.getFormation(), receivedCast.getFormation(), "mismatched Formation"); + assertEquals(createdCast.getAggregateMarking(), receivedCast.getAggregateMarking(), "mismatched AggregateMarking"); + assertEquals(createdCast.getDimensions(), receivedCast.getDimensions(), "mismatched Dimensions"); + assertEquals(createdCast.getOrientation(), receivedCast.getOrientation(), "mismatched Orientation"); + assertEquals(createdCast.getCenterOfMass(), receivedCast.getCenterOfMass(), "mismatched CenterOfMass"); + assertEquals(createdCast.getVelocity(), receivedCast.getVelocity(), "mismatched Velocity"); + assertEquals(createdCast.getAggregateIDList(), receivedCast.getAggregateIDList(), "mismatched AggregateIDList"); + assertEquals(createdCast.getEntityIDList(), receivedCast.getEntityIDList(), "mismatched EntityIDList"); + assertEquals(createdCast.getSilentAggregateSystemList(), receivedCast.getSilentAggregateSystemList(), "mismatched SilentAggregateSystemList"); + assertEquals(createdCast.getSilentEntitySystemList(), receivedCast.getSilentEntitySystemList(), "mismatched SilentEntitySystemList"); + assertEquals(createdCast.getVariableDatumList(), receivedCast.getVariableDatumList(), "mismatched VariableDatumList"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new AggregateStatePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/AntennaLocationTest.java b/test/edu/nps/moves/dis7/test/AntennaLocationTest.java new file mode 100644 index 0000000000..eac2abdb2f --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AntennaLocationTest.java @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.AntennaLocation; +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.dis7.pdus.Vector3Float; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for AntennaLocation data structure. + * Validates construction, field access, and marshal/unmarshal round-trip. + */ +@DisplayName("AntennaLocationTest") +public class AntennaLocationTest +{ + private static final float FLOAT_TOLERANCE = 1.0e-5f; + private static final double DOUBLE_TOLERANCE = 1.0e-10; + private static boolean verbose = true; + + /** default constructor */ + public AntennaLocationTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** AntennaLocationTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** AntennaLocationTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** AntennaLocationTest testDefaultConstructor()"); + + AntennaLocation al = new AntennaLocation(); + assertNotNull(al.getAntennaLocation(), "antennaLocation should not be null"); + assertNotNull(al.getRelativeAntennaLocation(), "relativeAntennaLocation should not be null"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** AntennaLocationTest testSettersAndGetters()"); + + AntennaLocation al = new AntennaLocation(); + al.getAntennaLocation().setX(-2685587.8486); + al.getAntennaLocation().setY(-4315429.2014); + al.getAntennaLocation().setZ(3836698.4738); + al.getRelativeAntennaLocation().setX(0.0f); + al.getRelativeAntennaLocation().setY(0.0f); + al.getRelativeAntennaLocation().setZ(2.5f); + + assertEquals(-2685587.8486, al.getAntennaLocation().getX(), DOUBLE_TOLERANCE, "mismatched antenna x"); + assertEquals(-4315429.2014, al.getAntennaLocation().getY(), DOUBLE_TOLERANCE, "mismatched antenna y"); + assertEquals(3836698.4738, al.getAntennaLocation().getZ(), DOUBLE_TOLERANCE, "mismatched antenna z"); + assertEquals(0.0f, al.getRelativeAntennaLocation().getX(), FLOAT_TOLERANCE, "mismatched relative x"); + assertEquals(0.0f, al.getRelativeAntennaLocation().getY(), FLOAT_TOLERANCE, "mismatched relative y"); + assertEquals(2.5f, al.getRelativeAntennaLocation().getZ(), FLOAT_TOLERANCE, "mismatched relative z"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** AntennaLocationTest testMarshalledSize()"); + + AntennaLocation al = new AntennaLocation(); + assertEquals(36, al.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** AntennaLocationTest testMarshalUnmarshalDataStream()"); + + AntennaLocation original = new AntennaLocation(); + original.getAntennaLocation().setX(100.0); + original.getAntennaLocation().setY(200.0); + original.getAntennaLocation().setZ(300.0); + original.getRelativeAntennaLocation().setX(1.0f); + original.getRelativeAntennaLocation().setY(2.0f); + original.getRelativeAntennaLocation().setZ(3.0f); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + AntennaLocation restored = new AntennaLocation(); + restored.unmarshal(dis); + + assertEquals(original.getAntennaLocation().getX(), restored.getAntennaLocation().getX(), DOUBLE_TOLERANCE, "mismatched antenna x after unmarshal"); + assertEquals(original.getAntennaLocation().getY(), restored.getAntennaLocation().getY(), DOUBLE_TOLERANCE, "mismatched antenna y after unmarshal"); + assertEquals(original.getAntennaLocation().getZ(), restored.getAntennaLocation().getZ(), DOUBLE_TOLERANCE, "mismatched antenna z after unmarshal"); + assertEquals(original.getRelativeAntennaLocation().getX(), restored.getRelativeAntennaLocation().getX(), FLOAT_TOLERANCE, "mismatched relative x after unmarshal"); + assertEquals(original.getRelativeAntennaLocation().getY(), restored.getRelativeAntennaLocation().getY(), FLOAT_TOLERANCE, "mismatched relative y after unmarshal"); + assertEquals(original.getRelativeAntennaLocation().getZ(), restored.getRelativeAntennaLocation().getZ(), FLOAT_TOLERANCE, "mismatched relative z after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** AntennaLocationTest testMarshalUnmarshalByteBuffer()"); + + AntennaLocation original = new AntennaLocation(); + original.getAntennaLocation().setX(-1000.5); + original.getAntennaLocation().setY(2000.5); + original.getAntennaLocation().setZ(3000.5); + original.getRelativeAntennaLocation().setX(0.5f); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + AntennaLocation restored = new AntennaLocation(); + restored.unmarshal(buffer); + + assertEquals(original.getAntennaLocation().getX(), restored.getAntennaLocation().getX(), DOUBLE_TOLERANCE, "mismatched antenna x after ByteBuffer unmarshal"); + assertEquals(original.getAntennaLocation().getY(), restored.getAntennaLocation().getY(), DOUBLE_TOLERANCE, "mismatched antenna y after ByteBuffer unmarshal"); + assertEquals(original.getAntennaLocation().getZ(), restored.getAntennaLocation().getZ(), DOUBLE_TOLERANCE, "mismatched antenna z after ByteBuffer unmarshal"); + assertEquals(original.getRelativeAntennaLocation().getX(), restored.getRelativeAntennaLocation().getX(), FLOAT_TOLERANCE, "mismatched relative x after ByteBuffer unmarshal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("AntennaLocationTest start"); + AntennaLocationTest test = new AntennaLocationTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + tearDownClass(); + System.out.println("AntennaLocationTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/AppearancePduTest.java b/test/edu/nps/moves/dis7/test/AppearancePduTest.java new file mode 100644 index 0000000000..281d87a864 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AppearancePduTest.java @@ -0,0 +1,121 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.AppearancePdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EntityMarking; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Appearance PDU fields and values. + */ +@DisplayName("AppearancePduTest") +public class AppearancePduTest extends PduTest +{ + /** default constructor */ + public AppearancePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** AppearancePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** AppearancePduTest testMultiplePdus()"); + + AppearancePdu appearancePdu = pduFactory.makeAppearancePdu(); + + appearancePdu.setLiveEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + appearancePdu.setForceId(ForceID.FRIENDLY); + appearancePdu.setEntityType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA).setCategory((byte) 1)); + appearancePdu.setAlternateEntityType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.AIR)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA).setCategory((byte) 2)); + appearancePdu.setEntityMarking(new EntityMarking().setCharacters("TestApp1".getBytes())); + testOnePdu(appearancePdu); + + appearancePdu.setForceId(ForceID.OPPOSING); + appearancePdu.setEntityMarking(new EntityMarking().setCharacters("TestApp2".getBytes())); + testOnePdu(appearancePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + AppearancePdu createdCast = (AppearancePdu) createdPdu; + AppearancePdu receivedCast = (AppearancePdu) receivedPdus.get(0); + + assertEquals(createdCast.getLiveEntityId(), receivedCast.getLiveEntityId(), "mismatched LiveEntityId"); + assertEquals(createdCast.getAppearanceFlags(), receivedCast.getAppearanceFlags(), "mismatched AppearanceFlags"); + assertEquals(createdCast.getForceId(), receivedCast.getForceId(), "mismatched ForceId"); + assertEquals(createdCast.getEntityType(), receivedCast.getEntityType(), "mismatched EntityType"); + assertEquals(createdCast.getAlternateEntityType(), receivedCast.getAlternateEntityType(), "mismatched AlternateEntityType"); + assertEquals(createdCast.getEntityMarking(), receivedCast.getEntityMarking(), "mismatched EntityMarking"); + assertEquals(createdCast.getCapabilities(), receivedCast.getCapabilities(), "mismatched Capabilities"); + assertEquals(createdCast.getAppearanceFields(), receivedCast.getAppearanceFields(), "mismatched AppearanceFields"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new AppearancePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ArealObjectStatePduTest.java b/test/edu/nps/moves/dis7/test/ArealObjectStatePduTest.java new file mode 100644 index 0000000000..3fe9a23ef5 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ArealObjectStatePduTest.java @@ -0,0 +1,123 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.ArealObjectStatePdu; +import edu.nps.moves.dis7.pdus.ObjectIdentifier; +import edu.nps.moves.dis7.pdus.ObjectType; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.ObjectKind; + +/** + * Unit tests for satisfactory handling of Areal Object State PDU fields and values. + */ +@DisplayName("ArealObjectStatePduTest") +public class ArealObjectStatePduTest extends PduTest +{ + /** default constructor */ + public ArealObjectStatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ArealObjectStatePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ArealObjectStatePduTest testMultiplePdus()"); + + ArealObjectStatePdu aosPdu = pduFactory.makeArealObjectStatePdu(); + + aosPdu.setObjectID(new ObjectIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + aosPdu.setForceID(ForceID.FRIENDLY); + aosPdu.setObjectType(new ObjectType().setDomain(PlatformDomain.LAND).setObjectKind(ObjectKind.OBSTACLE).setCategory((byte) 3)); + aosPdu.setRequesterID(new SimulationAddress().setSite(1).setApplication(2)); + aosPdu.setReceivingID(new SimulationAddress().setSite(3).setApplication(4)); + aosPdu.setUpdateNumber((short) 1); + testOnePdu(aosPdu); + + aosPdu.setUpdateNumber((short) 2); + aosPdu.setForceID(ForceID.NEUTRAL); + testOnePdu(aosPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ArealObjectStatePdu createdCast = (ArealObjectStatePdu) createdPdu; + ArealObjectStatePdu receivedCast = (ArealObjectStatePdu) receivedPdus.get(0); + + assertEquals(createdCast.getObjectID(), receivedCast.getObjectID(), "mismatched ObjectID"); + assertEquals(createdCast.getReferencedObjectID(), receivedCast.getReferencedObjectID(), "mismatched ReferencedObjectID"); + assertEquals(createdCast.getUpdateNumber(), receivedCast.getUpdateNumber(), "mismatched UpdateNumber"); + assertEquals(createdCast.getForceID(), receivedCast.getForceID(), "mismatched ForceID"); + assertEquals(createdCast.getModifications(), receivedCast.getModifications(), "mismatched Modifications"); + assertEquals(createdCast.getObjectType(), receivedCast.getObjectType(), "mismatched ObjectType"); + assertEquals(createdCast.getSpecificObjectAppearance(), receivedCast.getSpecificObjectAppearance(), "mismatched SpecificObjectAppearance"); + assertEquals(createdCast.getGeneralObjectAppearance(), receivedCast.getGeneralObjectAppearance(), "mismatched GeneralObjectAppearance"); + assertEquals(createdCast.getRequesterID(), receivedCast.getRequesterID(), "mismatched RequesterID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getObjectLocation(), receivedCast.getObjectLocation(), "mismatched ObjectLocation"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ArealObjectStatePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ArticulatedPartsPduTest.java b/test/edu/nps/moves/dis7/test/ArticulatedPartsPduTest.java new file mode 100644 index 0000000000..95ef3123fc --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ArticulatedPartsPduTest.java @@ -0,0 +1,103 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ArticulatedPartsPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Articulated Parts PDU fields and values. + */ +@DisplayName("ArticulatedPartsPduTest") +public class ArticulatedPartsPduTest extends PduTest +{ + /** default constructor */ + public ArticulatedPartsPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ArticulatedPartsPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ArticulatedPartsPduTest testMultiplePdus()"); + + ArticulatedPartsPdu artPartsPdu = pduFactory.makeArticulatedPartsPdu(); + + artPartsPdu.setLiveEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + testOnePdu(artPartsPdu); + + artPartsPdu.setLiveEntityId(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + testOnePdu(artPartsPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ArticulatedPartsPdu createdCast = (ArticulatedPartsPdu) createdPdu; + ArticulatedPartsPdu receivedCast = (ArticulatedPartsPdu) receivedPdus.get(0); + + assertEquals(createdCast.getLiveEntityId(), receivedCast.getLiveEntityId(), "mismatched LiveEntityId"); + assertEquals(createdCast.getVariableParameters(), receivedCast.getVariableParameters(), "mismatched VariableParameters"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ArticulatedPartsPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/AttributePduTest.java b/test/edu/nps/moves/dis7/test/AttributePduTest.java new file mode 100644 index 0000000000..3bc344a048 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/AttributePduTest.java @@ -0,0 +1,109 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.DISAttributeActionCode; +import edu.nps.moves.dis7.pdus.AttributePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Attribute PDU fields and values. + */ +@DisplayName("AttributePduTest") +public class AttributePduTest extends PduTest +{ + /** default constructor */ + public AttributePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** AttributePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** AttributePduTest testMultiplePdus()"); + + AttributePdu attrPdu = pduFactory.makeAttributePdu(); + + attrPdu.setOriginatingSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)); + attrPdu.setActionCode(DISAttributeActionCode.NO_STATEMENT); + testOnePdu(attrPdu); + + attrPdu.setOriginatingSimulationAddress(new SimulationAddress().setSite(3).setApplication(4)); + testOnePdu(attrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + AttributePdu createdCast = (AttributePdu) createdPdu; + AttributePdu receivedCast = (AttributePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingSimulationAddress(), receivedCast.getOriginatingSimulationAddress(), "mismatched OriginatingSimulationAddress"); + assertEquals(createdCast.getAttributeRecordPduType(), receivedCast.getAttributeRecordPduType(), "mismatched AttributeRecordPduType"); + assertEquals(createdCast.getAttributeRecordProtocolVersion(), receivedCast.getAttributeRecordProtocolVersion(), "mismatched AttributeRecordProtocolVersion"); + assertEquals(createdCast.getMasterAttributeRecordType(), receivedCast.getMasterAttributeRecordType(), "mismatched MasterAttributeRecordType"); + assertEquals(createdCast.getActionCode(), receivedCast.getActionCode(), "mismatched ActionCode"); + assertEquals(createdCast.getAttributeRecordSets(), receivedCast.getAttributeRecordSets(), "mismatched AttributeRecordSets"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new AttributePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ClockTimeTest.java b/test/edu/nps/moves/dis7/test/ClockTimeTest.java new file mode 100644 index 0000000000..648e563490 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ClockTimeTest.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ClockTime; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for ClockTime data structure. + * Validates construction, field access, and marshal/unmarshal round-trip. + */ +@DisplayName("ClockTimeTest") +public class ClockTimeTest +{ + private static boolean verbose = true; + + /** default constructor */ + public ClockTimeTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** ClockTimeTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** ClockTimeTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** ClockTimeTest testDefaultConstructor()"); + + ClockTime ct = new ClockTime(); + assertEquals(0, ct.getHour(), "mismatched default hour"); + assertEquals(0, ct.getTimePastHour(), "mismatched default timePastHour"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** ClockTimeTest testSettersAndGetters()"); + + ClockTime ct = new ClockTime(); + ct.setHour(14); + ct.setTimePastHour(1800000); + assertEquals(14, ct.getHour(), "mismatched hour"); + assertEquals(1800000, ct.getTimePastHour(), "mismatched timePastHour"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** ClockTimeTest testMarshalledSize()"); + + ClockTime ct = new ClockTime(); + assertEquals(8, ct.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** ClockTimeTest testMarshalUnmarshalDataStream()"); + + ClockTime original = new ClockTime(); + original.setHour(23); + original.setTimePastHour(3599999); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + ClockTime restored = new ClockTime(); + restored.unmarshal(dis); + + assertEquals(original.getHour(), restored.getHour(), "mismatched hour after unmarshal"); + assertEquals(original.getTimePastHour(), restored.getTimePastHour(), "mismatched timePastHour after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** ClockTimeTest testMarshalUnmarshalByteBuffer()"); + + ClockTime original = new ClockTime(); + original.setHour(0); + original.setTimePastHour(0); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + ClockTime restored = new ClockTime(); + restored.unmarshal(buffer); + + assertEquals(original.getHour(), restored.getHour(), "mismatched hour after ByteBuffer unmarshal"); + assertEquals(original.getTimePastHour(), restored.getTimePastHour(), "mismatched timePastHour after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** ClockTimeTest testEquality()"); + + ClockTime a = new ClockTime(); + a.setHour(5); + a.setTimePastHour(1000); + ClockTime b = new ClockTime(); + b.setHour(5); + b.setTimePastHour(1000); + ClockTime c = new ClockTime(); + c.setHour(5); + c.setTimePastHour(2000); + + assertTrue(a.equals(b), "equal ClockTimes should be equal"); + assertFalse(a.equals(c), "different ClockTimes should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("ClockTimeTest start"); + ClockTimeTest test = new ClockTimeTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("ClockTimeTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/CollisionElasticPduTest.java b/test/edu/nps/moves/dis7/test/CollisionElasticPduTest.java new file mode 100644 index 0000000000..0bf67bb36a --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CollisionElasticPduTest.java @@ -0,0 +1,141 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.CollisionElasticPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Collision Elastic PDU fields and values. + */ +@DisplayName("CollisionElasticPduTest") +public class CollisionElasticPduTest extends PduTest +{ + /** default constructor */ + public CollisionElasticPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** CollisionElasticPduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** CollisionElasticPduTest testMultiplePdus()"); + + CollisionElasticPdu collisionElasticPdu = pduFactory.makeCollisionElasticPdu(); + + collisionElasticPdu.setIssuingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + collisionElasticPdu.setCollidingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + collisionElasticPdu.setCollisionEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + collisionElasticPdu.setContactVelocity(new Vector3Float().setX(10.0f).setY(20.0f).setZ(30.0f)); + collisionElasticPdu.setMass(5000.0f); + collisionElasticPdu.setLocationOfImpact(new Vector3Float().setX(100.0f).setY(200.0f).setZ(300.0f)); + collisionElasticPdu.setCollisionIntermediateResultXX(1.0f); + collisionElasticPdu.setCollisionIntermediateResultXY(0.5f); + collisionElasticPdu.setCollisionIntermediateResultXZ(0.25f); + collisionElasticPdu.setCollisionIntermediateResultYY(2.0f); + collisionElasticPdu.setCollisionIntermediateResultYZ(0.75f); + collisionElasticPdu.setCollisionIntermediateResultZZ(3.0f); + collisionElasticPdu.setUnitSurfaceNormal(new Vector3Float().setX(0.0f).setY(0.0f).setZ(1.0f)); + collisionElasticPdu.setCoefficientOfRestitution(0.8f); + testOnePdu(collisionElasticPdu); + + collisionElasticPdu.setCollisionEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(collisionElasticPdu.setMass(8000.0f).setCoefficientOfRestitution(0.5f)); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + CollisionElasticPdu createdPduCast = (CollisionElasticPdu) createdPdu; + CollisionElasticPdu receivedPduCast = (CollisionElasticPdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdPduCast.getIssuingEntityID(), receivedPduCast.getIssuingEntityID(), "mismatched IssuingEntityID"); + assertEquals(createdPduCast.getCollidingEntityID(), receivedPduCast.getCollidingEntityID(), "mismatched CollidingEntityID"); + assertEquals(createdPduCast.getCollisionEventID(), receivedPduCast.getCollisionEventID(), "mismatched CollisionEventID"); + assertEquals(createdPduCast.getContactVelocity(), receivedPduCast.getContactVelocity(), "mismatched ContactVelocity"); + assertEquals(createdPduCast.getMass(), receivedPduCast.getMass(), "mismatched Mass"); + assertEquals(createdPduCast.getLocationOfImpact(), receivedPduCast.getLocationOfImpact(), "mismatched LocationOfImpact"); + assertEquals(createdPduCast.getCollisionIntermediateResultXX(), receivedPduCast.getCollisionIntermediateResultXX(), "mismatched CollisionIntermediateResultXX"); + assertEquals(createdPduCast.getCollisionIntermediateResultXY(), receivedPduCast.getCollisionIntermediateResultXY(), "mismatched CollisionIntermediateResultXY"); + assertEquals(createdPduCast.getCollisionIntermediateResultXZ(), receivedPduCast.getCollisionIntermediateResultXZ(), "mismatched CollisionIntermediateResultXZ"); + assertEquals(createdPduCast.getCollisionIntermediateResultYY(), receivedPduCast.getCollisionIntermediateResultYY(), "mismatched CollisionIntermediateResultYY"); + assertEquals(createdPduCast.getCollisionIntermediateResultYZ(), receivedPduCast.getCollisionIntermediateResultYZ(), "mismatched CollisionIntermediateResultYZ"); + assertEquals(createdPduCast.getCollisionIntermediateResultZZ(), receivedPduCast.getCollisionIntermediateResultZZ(), "mismatched CollisionIntermediateResultZZ"); + assertEquals(createdPduCast.getUnitSurfaceNormal(), receivedPduCast.getUnitSurfaceNormal(), "mismatched UnitSurfaceNormal"); + assertEquals(createdPduCast.getCoefficientOfRestitution(), receivedPduCast.getCoefficientOfRestitution(), "mismatched CoefficientOfRestitution"); + assertEquals(createdPduCast.getPad(), receivedPduCast.getPad(), "mismatched Pad"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest collisionElasticPduTest = new CollisionElasticPduTest(); + + collisionElasticPduTest.setUp(); + collisionElasticPduTest.testMultiplePdus(); + collisionElasticPduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/CollisionPduTest.java b/test/edu/nps/moves/dis7/test/CollisionPduTest.java new file mode 100644 index 0000000000..06f39833e3 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CollisionPduTest.java @@ -0,0 +1,127 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.CollisionPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Collision PDU fields and values. + */ +@DisplayName("CollisionPduTest") +public class CollisionPduTest extends PduTest +{ + /** default constructor */ + public CollisionPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** CollisionPduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** CollisionPduTest testMultiplePdus()"); + + CollisionPdu collisionPdu = pduFactory.makeCollisionPdu(); + + eventIdentifier.setEventNumber(incrementMasterEventNumber()); + collisionPdu.setEventID(eventIdentifier); + collisionPdu.setIssuingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + collisionPdu.setCollidingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + collisionPdu.setVelocity(new Vector3Float().setX(10.0f).setY(20.0f).setZ(30.0f)); + collisionPdu.setMass(5000.0f); + collisionPdu.setLocation(new Vector3Float().setX(100.0f).setY(200.0f).setZ(300.0f)); + testOnePdu(collisionPdu); + + collisionPdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(collisionPdu.setMass(7500.0f).setVelocity(new Vector3Float().setX(5.0f).setY(10.0f).setZ(15.0f))); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + CollisionPdu createdCollisionPdu = (CollisionPdu) createdPdu; + CollisionPdu receivedCollisionPdu = (CollisionPdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdCollisionPdu.getIssuingEntityID(), receivedCollisionPdu.getIssuingEntityID(), "mismatched IssuingEntityID"); + assertEquals(createdCollisionPdu.getCollidingEntityID(), receivedCollisionPdu.getCollidingEntityID(), "mismatched CollidingEntityID"); + assertEquals(createdCollisionPdu.getEventID(), receivedCollisionPdu.getEventID(), "mismatched EventID"); + assertEquals(createdCollisionPdu.getCollisionType(), receivedCollisionPdu.getCollisionType(), "mismatched CollisionType"); + assertEquals(createdCollisionPdu.getVelocity(), receivedCollisionPdu.getVelocity(), "mismatched Velocity"); + assertEquals(createdCollisionPdu.getMass(), receivedCollisionPdu.getMass(), "mismatched Mass"); + assertEquals(createdCollisionPdu.getLocation(), receivedCollisionPdu.getLocation(), "mismatched Location"); + assertEquals(createdCollisionPdu.getPad(), receivedCollisionPdu.getPad(), "mismatched Pad"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest collisionPduTest = new CollisionPduTest(); + + collisionPduTest.setUp(); + collisionPduTest.testMultiplePdus(); + collisionPduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/CommentReliablePduTest.java b/test/edu/nps/moves/dis7/test/CommentReliablePduTest.java new file mode 100644 index 0000000000..68fce18078 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CommentReliablePduTest.java @@ -0,0 +1,106 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.CommentReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Comment Reliable PDU fields and values. + */ +@DisplayName("CommentReliablePduTest") +public class CommentReliablePduTest extends PduTest +{ + /** default constructor */ + public CommentReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** CommentReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** CommentReliablePduTest testMultiplePdus()"); + + CommentReliablePdu crPdu = pduFactory.makeCommentReliablePdu(); + + crPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + crPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + testOnePdu(crPdu); + + crPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(5).setApplication(6))); + testOnePdu(crPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + CommentReliablePdu createdCast = (CommentReliablePdu) createdPdu; + CommentReliablePdu receivedCast = (CommentReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new CommentReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/CoordinateConversionsTest.java b/test/edu/nps/moves/dis7/test/CoordinateConversionsTest.java new file mode 100644 index 0000000000..b9c411a317 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CoordinateConversionsTest.java @@ -0,0 +1,275 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.CoordinateConversions; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for CoordinateConversions utility class. + * Validates WGS84 ECEF (xyz) to geodetic (lat/lon/alt) conversions and vice versa. + * Reference values computed from known geodetic coordinates. + */ +@DisplayName("CoordinateConversionsTest") +public class CoordinateConversionsTest +{ + /** tolerance for lat/lon round-trip in radians (sub-millimeter surface accuracy) */ + private static final double LAT_LON_TOLERANCE_RAD = 1.0e-10; + + /** tolerance for altitude round-trip in meters */ + private static final double ALT_TOLERANCE_M = 0.01; + + /** tolerance for xyz round-trip in meters */ + private static final double XYZ_TOLERANCE_M = 0.01; + + /** verbose output flag */ + private static boolean verbose = true; + + /** default constructor */ + public CoordinateConversionsTest() + { + } + + /** preparation */ + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest setUpClass()"); + } + + /** cleanup */ + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest tearDownClass()"); + } + + /** + * Test conversion constants are correct + */ + @Test + public void testConversionConstants() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testConversionConstants()"); + + assertEquals(180.0 / Math.PI, CoordinateConversions.RADIANS_TO_DEGREES, 1.0e-12, "mismatched RADIANS_TO_DEGREES"); + assertEquals(Math.PI / 180.0, CoordinateConversions.DEGREES_TO_RADIANS, 1.0e-12, "mismatched DEGREES_TO_RADIANS"); + assertEquals(1.0, CoordinateConversions.RADIANS_TO_DEGREES * CoordinateConversions.DEGREES_TO_RADIANS, 1.0e-12, "conversion constants should be inverses"); + } + + /** + * Test round-trip: lat/lon/alt (radians) -> xyz -> lat/lon/alt (radians) + * Using NPS Monterey, CA as reference point (36.5967N, 121.8770W, 0m) + */ + @Test + public void testRoundTripMonterey() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testRoundTripMonterey()"); + + double latRad = 36.5967 * CoordinateConversions.DEGREES_TO_RADIANS; + double lonRad = -121.8770 * CoordinateConversions.DEGREES_TO_RADIANS; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + assertNotNull(xyz, "xyz result should not be null"); + assertEquals(3, xyz.length, "xyz should have 3 elements"); + + double[] latLonAlt = CoordinateConversions.xyzToLatLonRadians(xyz); + assertNotNull(latLonAlt, "latLonAlt result should not be null"); + assertEquals(3, latLonAlt.length, "latLonAlt should have 3 elements"); + + assertEquals(latRad, latLonAlt[0], LAT_LON_TOLERANCE_RAD, "mismatched latitude after round-trip"); + assertEquals(lonRad, latLonAlt[1], LAT_LON_TOLERANCE_RAD, "mismatched longitude after round-trip"); + assertEquals(altM, latLonAlt[2], ALT_TOLERANCE_M, "mismatched altitude after round-trip"); + } + + /** + * Test round-trip with altitude: lat/lon/alt (radians) -> xyz -> lat/lon/alt (radians) + * Using NPS Monterey at 100m elevation + */ + @Test + public void testRoundTripWithAltitude() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testRoundTripWithAltitude()"); + + double latRad = 36.5967 * CoordinateConversions.DEGREES_TO_RADIANS; + double lonRad = -121.8770 * CoordinateConversions.DEGREES_TO_RADIANS; + double altM = 100.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + double[] latLonAlt = CoordinateConversions.xyzToLatLonRadians(xyz); + + assertEquals(latRad, latLonAlt[0], LAT_LON_TOLERANCE_RAD, "mismatched latitude after round-trip with altitude"); + assertEquals(lonRad, latLonAlt[1], LAT_LON_TOLERANCE_RAD, "mismatched longitude after round-trip with altitude"); + assertEquals(altM, latLonAlt[2], ALT_TOLERANCE_M, "mismatched altitude after round-trip with altitude"); + } + + /** + * Test round-trip using degree convenience methods + * Using Washington DC (38.8977N, 77.0365W, 0m) + */ + @Test + public void testRoundTripDegrees() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testRoundTripDegrees()"); + + double latDeg = 38.8977; + double lonDeg = -77.0365; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonDegrees(latDeg, lonDeg, altM); + double[] latLonAltDeg = CoordinateConversions.xyzToLatLonDegrees(xyz); + + double tolerance = LAT_LON_TOLERANCE_RAD * CoordinateConversions.RADIANS_TO_DEGREES; + assertEquals(latDeg, latLonAltDeg[0], tolerance, "mismatched latitude (degrees) after round-trip"); + assertEquals(lonDeg, latLonAltDeg[1], tolerance, "mismatched longitude (degrees) after round-trip"); + assertEquals(altM, latLonAltDeg[2], ALT_TOLERANCE_M, "mismatched altitude after round-trip"); + } + + /** + * Test equator/prime meridian intersection (0, 0, 0) + */ + @Test + public void testEquatorPrimeMeridian() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testEquatorPrimeMeridian()"); + + double latRad = 0.0; + double lonRad = 0.0; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + + // at equator/prime meridian, x should be the semi-major axis, y and z should be 0 + double semiMajorAxis = 6378137.0; + assertEquals(semiMajorAxis, xyz[0], XYZ_TOLERANCE_M, "mismatched X at equator/prime meridian"); + assertEquals(0.0, xyz[1], XYZ_TOLERANCE_M, "mismatched Y at equator/prime meridian"); + assertEquals(0.0, xyz[2], XYZ_TOLERANCE_M, "mismatched Z at equator/prime meridian"); + + // round-trip + double[] latLonAlt = CoordinateConversions.xyzToLatLonRadians(xyz); + assertEquals(latRad, latLonAlt[0], LAT_LON_TOLERANCE_RAD, "mismatched latitude at equator/prime meridian"); + assertEquals(lonRad, latLonAlt[1], LAT_LON_TOLERANCE_RAD, "mismatched longitude at equator/prime meridian"); + assertEquals(altM, latLonAlt[2], ALT_TOLERANCE_M, "mismatched altitude at equator/prime meridian"); + } + + /** + * Test equator at 90 degrees east (0, 90E, 0) + */ + @Test + public void testEquator90East() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testEquator90East()"); + + double latRad = 0.0; + double lonRad = 90.0 * CoordinateConversions.DEGREES_TO_RADIANS; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + + // at equator/90E, y should be the semi-major axis, x and z should be 0 + double semiMajorAxis = 6378137.0; + assertEquals(0.0, xyz[0], XYZ_TOLERANCE_M, "mismatched X at equator/90E"); + assertEquals(semiMajorAxis, xyz[1], XYZ_TOLERANCE_M, "mismatched Y at equator/90E"); + assertEquals(0.0, xyz[2], XYZ_TOLERANCE_M, "mismatched Z at equator/90E"); + } + + /** + * Test north pole (90N, 0, 0) + * Note: the algorithm comments state it may not be 100% accurate near poles + */ + @Test + public void testNorthPole() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testNorthPole()"); + + double latRad = 90.0 * CoordinateConversions.DEGREES_TO_RADIANS; + double lonRad = 0.0; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + + // at north pole, x and y should be ~0, z should be the semi-minor axis + double semiMinorAxis = 6356752.3142; + assertEquals(0.0, xyz[0], XYZ_TOLERANCE_M, "mismatched X at north pole"); + assertEquals(0.0, xyz[1], XYZ_TOLERANCE_M, "mismatched Y at north pole"); + assertEquals(semiMinorAxis, xyz[2], XYZ_TOLERANCE_M, "mismatched Z at north pole"); + } + + /** + * Test southern hemisphere: Sydney, Australia (33.8688S, 151.2093E, 0m) + */ + @Test + public void testSouthernHemisphere() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testSouthernHemisphere()"); + + double latRad = -33.8688 * CoordinateConversions.DEGREES_TO_RADIANS; + double lonRad = 151.2093 * CoordinateConversions.DEGREES_TO_RADIANS; + double altM = 0.0; + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + double[] latLonAlt = CoordinateConversions.xyzToLatLonRadians(xyz); + + assertEquals(latRad, latLonAlt[0], LAT_LON_TOLERANCE_RAD, "mismatched latitude for southern hemisphere"); + assertEquals(lonRad, latLonAlt[1], LAT_LON_TOLERANCE_RAD, "mismatched longitude for southern hemisphere"); + assertEquals(altM, latLonAlt[2], ALT_TOLERANCE_M, "mismatched altitude for southern hemisphere"); + } + + /** + * Test high altitude: geostationary orbit (~35786 km) + */ + @Test + public void testHighAltitude() + { + if (verbose) + System.out.println("*** CoordinateConversionsTest testHighAltitude()"); + + double latRad = 0.0; + double lonRad = 0.0; + double altM = 35786000.0; // geostationary orbit + + double[] xyz = CoordinateConversions.getXYZfromLatLonRadians(latRad, lonRad, altM); + double[] latLonAlt = CoordinateConversions.xyzToLatLonRadians(xyz); + + assertEquals(latRad, latLonAlt[0], LAT_LON_TOLERANCE_RAD, "mismatched latitude at high altitude"); + assertEquals(lonRad, latLonAlt[1], LAT_LON_TOLERANCE_RAD, "mismatched longitude at high altitude"); + assertEquals(altM, latLonAlt[2], 1.0, "mismatched altitude at high altitude (relaxed tolerance)"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("CoordinateConversionsTest start"); + CoordinateConversionsTest test = new CoordinateConversionsTest(); + + setUpClass(); + test.testConversionConstants(); + test.testRoundTripMonterey(); + test.testRoundTripWithAltitude(); + test.testRoundTripDegrees(); + test.testEquatorPrimeMeridian(); + test.testEquator90East(); + test.testNorthPole(); + test.testSouthernHemisphere(); + test.testHighAltitude(); + tearDownClass(); + + System.out.println("CoordinateConversionsTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/CreateEntityPduTest.java b/test/edu/nps/moves/dis7/test/CreateEntityPduTest.java new file mode 100644 index 0000000000..0a9695a52a --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CreateEntityPduTest.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.CreateEntityPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Create Entity PDU fields and values. + */ +@DisplayName("CreateEntityPduTest") +public class CreateEntityPduTest extends PduTest +{ + /** default constructor */ + public CreateEntityPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** CreateEntityPduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** CreateEntityPduTest testMultiplePdus()"); + + CreateEntityPdu createEntityPdu = pduFactory.makeCreateEntityPdu(); + + createEntityPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + createEntityPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + createEntityPdu.setRequestID(1001); + testOnePdu(createEntityPdu); + + createEntityPdu.setRequestID(1002); + testOnePdu(createEntityPdu); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + CreateEntityPdu createdCreateEntityPdu = (CreateEntityPdu) createdPdu; + CreateEntityPdu receivedCreateEntityPdu = (CreateEntityPdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdCreateEntityPdu.getOriginatingID(), receivedCreateEntityPdu.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCreateEntityPdu.getReceivingID(), receivedCreateEntityPdu.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCreateEntityPdu.getRequestID(), receivedCreateEntityPdu.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest createEntityPduTest = new CreateEntityPduTest(); + + createEntityPduTest.setUp(); + createEntityPduTest.testMultiplePdus(); + createEntityPduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/CreateEntityReliablePduTest.java b/test/edu/nps/moves/dis7/test/CreateEntityReliablePduTest.java new file mode 100644 index 0000000000..fdbeecbf96 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/CreateEntityReliablePduTest.java @@ -0,0 +1,111 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.CreateEntityReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Create Entity Reliable PDU fields and values. + */ +@DisplayName("CreateEntityReliablePduTest") +public class CreateEntityReliablePduTest extends PduTest +{ + /** default constructor */ + public CreateEntityReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** CreateEntityReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** CreateEntityReliablePduTest testMultiplePdus()"); + + CreateEntityReliablePdu cerPdu = pduFactory.makeCreateEntityReliablePdu(); + + cerPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + cerPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + cerPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + cerPdu.setRequestID(101); + testOnePdu(cerPdu); + + cerPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + cerPdu.setRequestID(102); + testOnePdu(cerPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + CreateEntityReliablePdu createdCast = (CreateEntityReliablePdu) createdPdu; + CreateEntityReliablePdu receivedCast = (CreateEntityReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new CreateEntityReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DataPduTest.java b/test/edu/nps/moves/dis7/test/DataPduTest.java new file mode 100644 index 0000000000..7f26a18c05 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DataPduTest.java @@ -0,0 +1,114 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.DataPdu; +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import edu.nps.moves.dis7.enumerations.VariableRecordType; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Data PDU fields and values. + */ +@DisplayName("DataPduTest") +public class DataPduTest extends PduTest +{ + /** default constructor */ + public DataPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DataPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DataPduTest testMultiplePdus()"); + + DataPdu dataPdu = pduFactory.makeDataPdu(); + + dataPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + dataPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + dataPdu.setRequestID(8001); + dataPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(55)); + dataPdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST).setVariableDatumValue(new byte[]{1, 2, 3, 4, 5, 6, 7, 8})); + testOnePdu(dataPdu); + + dataPdu.setRequestID(8002); + testOnePdu(dataPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + DataPdu createdCast = (DataPdu) createdPdu; + DataPdu receivedCast = (DataPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new DataPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DataQueryPduTest.java b/test/edu/nps/moves/dis7/test/DataQueryPduTest.java new file mode 100644 index 0000000000..82a0f8237c --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DataQueryPduTest.java @@ -0,0 +1,117 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.DataQueryPdu; +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.VariableRecordType; + +/** + * Unit tests for satisfactory handling of Data Query PDU fields and values. + */ +@DisplayName("DataQueryPduTest") +public class DataQueryPduTest extends PduTest +{ + /** default constructor */ + public DataQueryPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DataQueryPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DataQueryPduTest testMultiplePdus()"); + + DataQueryPdu dataQueryPdu = pduFactory.makeDataQueryPdu(); + + dataQueryPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + dataQueryPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + dataQueryPdu.setRequestID(9001); + dataQueryPdu.setTimeInterval(5000); + dataQueryPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST)); + dataQueryPdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST)); + testOnePdu(dataQueryPdu); + + dataQueryPdu.setRequestID(9002); + dataQueryPdu.setTimeInterval(10000); + testOnePdu(dataQueryPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + DataQueryPdu createdCast = (DataQueryPdu) createdPdu; + DataQueryPdu receivedCast = (DataQueryPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getTimeInterval(), receivedCast.getTimeInterval(), "mismatched TimeInterval"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new DataQueryPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DataQueryReliablePduTest.java b/test/edu/nps/moves/dis7/test/DataQueryReliablePduTest.java new file mode 100644 index 0000000000..9b2351cb9b --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DataQueryReliablePduTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.DataQueryReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Data Query Reliable PDU fields and values. + */ +@DisplayName("DataQueryReliablePduTest") +public class DataQueryReliablePduTest extends PduTest +{ + /** default constructor */ + public DataQueryReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DataQueryReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DataQueryReliablePduTest testMultiplePdus()"); + + DataQueryReliablePdu dqrPdu = pduFactory.makeDataQueryReliablePdu(); + + dqrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + dqrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + dqrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + dqrPdu.setRequestID(901); + dqrPdu.setTimeInterval(5000); + testOnePdu(dqrPdu); + + dqrPdu.setRequestID(902); + dqrPdu.setTimeInterval(10000); + testOnePdu(dqrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + DataQueryReliablePdu createdCast = (DataQueryReliablePdu) createdPdu; + DataQueryReliablePdu receivedCast = (DataQueryReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getTimeInterval(), receivedCast.getTimeInterval(), "mismatched TimeInterval"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new DataQueryReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DataReliablePduTest.java b/test/edu/nps/moves/dis7/test/DataReliablePduTest.java new file mode 100644 index 0000000000..5e132cea20 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DataReliablePduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.DataReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Data Reliable PDU fields and values. + */ +@DisplayName("DataReliablePduTest") +public class DataReliablePduTest extends PduTest +{ + /** default constructor */ + public DataReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DataReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DataReliablePduTest testMultiplePdus()"); + + DataReliablePdu drPdu = pduFactory.makeDataReliablePdu(); + + drPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + drPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + drPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + drPdu.setRequestID(801); + testOnePdu(drPdu); + + drPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + drPdu.setRequestID(802); + testOnePdu(drPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + DataReliablePdu createdCast = (DataReliablePdu) createdPdu; + DataReliablePdu receivedCast = (DataReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new DataReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DeadReckoningParametersTest.java b/test/edu/nps/moves/dis7/test/DeadReckoningParametersTest.java new file mode 100644 index 0000000000..07d1eed451 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DeadReckoningParametersTest.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.DeadReckoningParameters; +import edu.nps.moves.dis7.pdus.Vector3Float; +import edu.nps.moves.dis7.enumerations.DeadReckoningAlgorithm; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for DeadReckoningParameters data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and algorithm types. + */ +@DisplayName("DeadReckoningParametersTest") +public class DeadReckoningParametersTest +{ + private static final float TOLERANCE = 1.0e-5f; + private static boolean verbose = true; + + /** default constructor */ + public DeadReckoningParametersTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest testDefaultConstructor()"); + + DeadReckoningParameters drp = new DeadReckoningParameters(); + assertNotNull(drp.getEntityLinearAcceleration(), "entityLinearAcceleration should not be null"); + assertNotNull(drp.getEntityAngularVelocity(), "entityAngularVelocity should not be null"); + assertNotNull(drp.getParameters(), "parameters array should not be null"); + assertEquals(15, drp.getParameters().length, "parameters array should be 15 bytes"); + } + + @Test + public void testSetAlgorithm() + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest testSetAlgorithm()"); + + DeadReckoningParameters drp = new DeadReckoningParameters(); + drp.setDeadReckoningAlgorithm(DeadReckoningAlgorithm.DRM_FPW_CONSTANT_VELOCITY_LOW_ACCELERATION_LINEAR_MOTION_ENTITY); + assertEquals(DeadReckoningAlgorithm.DRM_FPW_CONSTANT_VELOCITY_LOW_ACCELERATION_LINEAR_MOTION_ENTITY, + drp.getDeadReckoningAlgorithm(), "mismatched algorithm"); + } + + @Test + public void testSetAccelerationAndVelocity() + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest testSetAccelerationAndVelocity()"); + + DeadReckoningParameters drp = new DeadReckoningParameters(); + Vector3Float accel = new Vector3Float(); + accel.setX(1.0f); + accel.setY(2.0f); + accel.setZ(3.0f); + drp.setEntityLinearAcceleration(accel); + + Vector3Float angVel = new Vector3Float(); + angVel.setX(0.1f); + angVel.setY(0.2f); + angVel.setZ(0.3f); + drp.setEntityAngularVelocity(angVel); + + assertEquals(1.0f, drp.getEntityLinearAcceleration().getX(), TOLERANCE, "mismatched accel x"); + assertEquals(2.0f, drp.getEntityLinearAcceleration().getY(), TOLERANCE, "mismatched accel y"); + assertEquals(3.0f, drp.getEntityLinearAcceleration().getZ(), TOLERANCE, "mismatched accel z"); + assertEquals(0.1f, drp.getEntityAngularVelocity().getX(), TOLERANCE, "mismatched angVel x"); + assertEquals(0.2f, drp.getEntityAngularVelocity().getY(), TOLERANCE, "mismatched angVel y"); + assertEquals(0.3f, drp.getEntityAngularVelocity().getZ(), TOLERANCE, "mismatched angVel z"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest testMarshalUnmarshalDataStream()"); + + DeadReckoningParameters original = new DeadReckoningParameters(); + original.setDeadReckoningAlgorithm(DeadReckoningAlgorithm.DRM_FPW_CONSTANT_VELOCITY_LOW_ACCELERATION_LINEAR_MOTION_ENTITY); + original.getEntityLinearAcceleration().setX(5.0f); + original.getEntityLinearAcceleration().setY(10.0f); + original.getEntityLinearAcceleration().setZ(15.0f); + original.getEntityAngularVelocity().setX(0.5f); + original.getEntityAngularVelocity().setY(1.0f); + original.getEntityAngularVelocity().setZ(1.5f); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + DeadReckoningParameters restored = new DeadReckoningParameters(); + restored.unmarshal(dis); + + assertEquals(original.getDeadReckoningAlgorithm(), restored.getDeadReckoningAlgorithm(), "mismatched algorithm after unmarshal"); + assertEquals(original.getEntityLinearAcceleration().getX(), restored.getEntityLinearAcceleration().getX(), TOLERANCE, "mismatched accel x after unmarshal"); + assertEquals(original.getEntityLinearAcceleration().getY(), restored.getEntityLinearAcceleration().getY(), TOLERANCE, "mismatched accel y after unmarshal"); + assertEquals(original.getEntityLinearAcceleration().getZ(), restored.getEntityLinearAcceleration().getZ(), TOLERANCE, "mismatched accel z after unmarshal"); + assertEquals(original.getEntityAngularVelocity().getX(), restored.getEntityAngularVelocity().getX(), TOLERANCE, "mismatched angVel x after unmarshal"); + assertEquals(original.getEntityAngularVelocity().getY(), restored.getEntityAngularVelocity().getY(), TOLERANCE, "mismatched angVel y after unmarshal"); + assertEquals(original.getEntityAngularVelocity().getZ(), restored.getEntityAngularVelocity().getZ(), TOLERANCE, "mismatched angVel z after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** DeadReckoningParametersTest testMarshalUnmarshalByteBuffer()"); + + DeadReckoningParameters original = new DeadReckoningParameters(); + original.setDeadReckoningAlgorithm(DeadReckoningAlgorithm.DRM_RVW_HIGH_SPEED_OR_MANEUVERING_ENTITY_WITH_EXTRAPOLATION_OF_ORIENTATION); + original.getEntityLinearAcceleration().setX(-1.0f); + original.getEntityAngularVelocity().setZ(0.99f); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + DeadReckoningParameters restored = new DeadReckoningParameters(); + restored.unmarshal(buffer); + + assertEquals(original.getDeadReckoningAlgorithm(), restored.getDeadReckoningAlgorithm(), "mismatched algorithm after ByteBuffer unmarshal"); + assertEquals(original.getEntityLinearAcceleration().getX(), restored.getEntityLinearAcceleration().getX(), TOLERANCE, "mismatched accel x after ByteBuffer unmarshal"); + assertEquals(original.getEntityAngularVelocity().getZ(), restored.getEntityAngularVelocity().getZ(), TOLERANCE, "mismatched angVel z after ByteBuffer unmarshal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("DeadReckoningParametersTest start"); + DeadReckoningParametersTest test = new DeadReckoningParametersTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSetAlgorithm(); + test.testSetAccelerationAndVelocity(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + tearDownClass(); + System.out.println("DeadReckoningParametersTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/DesignatorPduTest.java b/test/edu/nps/moves/dis7/test/DesignatorPduTest.java new file mode 100644 index 0000000000..27c45562fa --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DesignatorPduTest.java @@ -0,0 +1,119 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.DesignatorPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Designator PDU fields and values. + */ +@DisplayName("DesignatorPduTest") +public class DesignatorPduTest extends PduTest +{ + /** default constructor */ + public DesignatorPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DesignatorPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DesignatorPduTest testMultiplePdus()"); + + DesignatorPdu designatorPdu = pduFactory.makeDesignatorPdu(); + + designatorPdu.setDesignatingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + designatorPdu.setDesignatedEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + designatorPdu.setDesignatorPower(500.0f); + designatorPdu.setDesignatorWavelength(1.064f); + designatorPdu.setDesignatorSpotWrtDesignated(new Vector3Float().setX(10.0f).setY(20.0f).setZ(5.0f)); + designatorPdu.setDesignatorSpotLocation(new Vector3Double().setX(1000.0).setY(2000.0).setZ(3000.0)); + testOnePdu(designatorPdu); + + designatorPdu.setDesignatorPower(1000.0f); + designatorPdu.setDesignatorWavelength(0.532f); + testOnePdu(designatorPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + DesignatorPdu createdCast = (DesignatorPdu) createdPdu; + DesignatorPdu receivedCast = (DesignatorPdu) receivedPdus.get(0); + + assertEquals(createdCast.getDesignatingEntityID(), receivedCast.getDesignatingEntityID(), "mismatched DesignatingEntityID"); + assertEquals(createdCast.getCodeName(), receivedCast.getCodeName(), "mismatched CodeName"); + assertEquals(createdCast.getDesignatedEntityID(), receivedCast.getDesignatedEntityID(), "mismatched DesignatedEntityID"); + assertEquals(createdCast.getDesignatorCode(), receivedCast.getDesignatorCode(), "mismatched DesignatorCode"); + assertEquals(createdCast.getDesignatorPower(), receivedCast.getDesignatorPower(), "mismatched DesignatorPower"); + assertEquals(createdCast.getDesignatorWavelength(), receivedCast.getDesignatorWavelength(), "mismatched DesignatorWavelength"); + assertEquals(createdCast.getDesignatorSpotWrtDesignated(), receivedCast.getDesignatorSpotWrtDesignated(), "mismatched DesignatorSpotWrtDesignated"); + assertEquals(createdCast.getDesignatorSpotLocation(), receivedCast.getDesignatorSpotLocation(), "mismatched DesignatorSpotLocation"); + assertEquals(createdCast.getDeadReckoningAlgorithm(), receivedCast.getDeadReckoningAlgorithm(), "mismatched DeadReckoningAlgorithm"); + assertEquals(createdCast.getEntityLinearAcceleration(), receivedCast.getEntityLinearAcceleration(), "mismatched EntityLinearAcceleration"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new DesignatorPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DirectedEnergyFirePduTest.java b/test/edu/nps/moves/dis7/test/DirectedEnergyFirePduTest.java new file mode 100644 index 0000000000..3acf21a2dc --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DirectedEnergyFirePduTest.java @@ -0,0 +1,133 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.DirectedEnergyFirePdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Directed Energy Fire PDU fields and values. + */ +@DisplayName("DirectedEnergyFirePduTest") +public class DirectedEnergyFirePduTest extends PduTest +{ + /** default constructor */ + public DirectedEnergyFirePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** DirectedEnergyFirePduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** DirectedEnergyFirePduTest testMultiplePdus()"); + + DirectedEnergyFirePdu dePdu = pduFactory.makeDirectedEnergyFirePdu(); + + dePdu.setFiringEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + dePdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + dePdu.setApertureEmitterLocation(new Vector3Float().setX(10.0f).setY(20.0f).setZ(5.0f)); + dePdu.setApertureDiameter(0.5f); + dePdu.setWavelength(1.064f); + dePdu.setCommulativeShotTime(2.5f); + dePdu.setPulseRepititionFrequency(10.0f); + dePdu.setPulseWidth(0.001f); + testOnePdu(dePdu); + + dePdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(dePdu.setWavelength(0.532f).setApertureDiameter(1.0f)); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + DirectedEnergyFirePdu createdDePdu = (DirectedEnergyFirePdu) createdPdu; + DirectedEnergyFirePdu receivedDePdu = (DirectedEnergyFirePdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdDePdu.getFiringEntityID(), receivedDePdu.getFiringEntityID(), "mismatched FiringEntityID"); + assertEquals(createdDePdu.getEventID(), receivedDePdu.getEventID(), "mismatched EventID"); + assertEquals(createdDePdu.getMunitionType(), receivedDePdu.getMunitionType(), "mismatched MunitionType"); + assertEquals(createdDePdu.getShotStartTime(), receivedDePdu.getShotStartTime(), "mismatched ShotStartTime"); + assertEquals(createdDePdu.getCommulativeShotTime(), receivedDePdu.getCommulativeShotTime(), "mismatched CommulativeShotTime"); + assertEquals(createdDePdu.getApertureEmitterLocation(), receivedDePdu.getApertureEmitterLocation(), "mismatched ApertureEmitterLocation"); + assertEquals(createdDePdu.getApertureDiameter(), receivedDePdu.getApertureDiameter(), "mismatched ApertureDiameter"); + assertEquals(createdDePdu.getWavelength(), receivedDePdu.getWavelength(), "mismatched Wavelength"); + assertEquals(createdDePdu.getPulseRepititionFrequency(), receivedDePdu.getPulseRepititionFrequency(), "mismatched PulseRepititionFrequency"); + assertEquals(createdDePdu.getPulseWidth(), receivedDePdu.getPulseWidth(), "mismatched PulseWidth"); + assertEquals(createdDePdu.getFlags(), receivedDePdu.getFlags(), "mismatched Flags"); + assertEquals(createdDePdu.getPulseShape(), receivedDePdu.getPulseShape(), "mismatched PulseShape"); + assertEquals(createdDePdu.getDERecords(), receivedDePdu.getDERecords(), "mismatched DERecords"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest dePduTest = new DirectedEnergyFirePduTest(); + + dePduTest.setUp(); + dePduTest.testMultiplePdus(); + dePduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/DisChannelTest.java b/test/edu/nps/moves/dis7/test/DisChannelTest.java new file mode 100644 index 0000000000..c241f74f27 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DisChannelTest.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.DisChannel; +import edu.nps.moves.dis7.utilities.DisTime.TimestampStyle; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for DisChannel utility class. + * Tests configuration and parameter access without requiring network. + */ +@DisplayName("DisChannelTest") +public class DisChannelTest +{ + private static boolean verbose = true; + + /** default constructor */ + public DisChannelTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** DisChannelTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** DisChannelTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** DisChannelTest testDefaultConstructor()"); + + DisChannel channel = new DisChannel(); + assertNotNull(channel, "channel should not be null"); + } + + @Test + public void testDescriptorConstructor() + { + if (verbose) + System.out.println("*** DisChannelTest testDescriptorConstructor()"); + + DisChannel channel = new DisChannel("test channel"); + assertEquals("test channel", channel.getDescriptor(), "mismatched descriptor"); + } + + @Test + public void testDefaultNetworkAddress() + { + if (verbose) + System.out.println("*** DisChannelTest testDefaultNetworkAddress()"); + + DisChannel channel = new DisChannel(); + assertEquals("239.1.2.3", channel.getNetworkAddress(), "mismatched default network address"); + } + + @Test + public void testDefaultNetworkPort() + { + if (verbose) + System.out.println("*** DisChannelTest testDefaultNetworkPort()"); + + DisChannel channel = new DisChannel(); + assertEquals(3000, channel.getNetworkPort(), "mismatched default network port"); + } + + @Test + public void testSetNetworkAddress() + { + if (verbose) + System.out.println("*** DisChannelTest testSetNetworkAddress()"); + + DisChannel channel = new DisChannel(); + channel.setNetworkAddress("239.1.2.4"); + assertEquals("239.1.2.4", channel.getNetworkAddress(), "mismatched network address after set"); + } + + @Test + public void testSetNetworkPort() + { + if (verbose) + System.out.println("*** DisChannelTest testSetNetworkPort()"); + + DisChannel channel = new DisChannel(); + channel.setNetworkPort(4000); + assertEquals(4000, channel.getNetworkPort(), "mismatched network port after set"); + } + + @Test + public void testSetDescriptor() + { + if (verbose) + System.out.println("*** DisChannelTest testSetDescriptor()"); + + DisChannel channel = new DisChannel(); + channel.setDescriptor("updated descriptor"); + assertEquals("updated descriptor", channel.getDescriptor(), "mismatched descriptor after set"); + } + + @Test + public void testTimestampStyle() + { + if (verbose) + System.out.println("*** DisChannelTest testTimestampStyle()"); + + DisChannel channel = new DisChannel(); + channel.setTimestampStyle(TimestampStyle.IEEE_RELATIVE); + assertEquals(TimestampStyle.IEEE_RELATIVE, channel.getTimestampStyle(), "mismatched timestamp style"); + } + + @Test + public void testGetPduFactory() + { + if (verbose) + System.out.println("*** DisChannelTest testGetPduFactory()"); + + DisChannel channel = new DisChannel(); + assertNotNull(channel.getPduFactory(), "PduFactory should not be null"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("DisChannelTest start"); + DisChannelTest test = new DisChannelTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testDescriptorConstructor(); + test.testDefaultNetworkAddress(); + test.testDefaultNetworkPort(); + test.testSetNetworkAddress(); + test.testSetNetworkPort(); + test.testSetDescriptor(); + test.testTimestampStyle(); + test.testGetPduFactory(); + tearDownClass(); + System.out.println("DisChannelTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/DisTimeTest.java b/test/edu/nps/moves/dis7/test/DisTimeTest.java new file mode 100644 index 0000000000..d1d9678365 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/DisTimeTest.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.DisTime; +import edu.nps.moves.dis7.utilities.DisTime.TimestampStyle; +import edu.nps.moves.dis7.utilities.DisTime.TimeFormatterType; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for DisTime utility class. + * Validates timestamp styles, formatters, epoch handling, and conversions. + */ +@DisplayName("DisTimeTest") +public class DisTimeTest +{ + private static boolean verbose = true; + + /** default constructor */ + public DisTimeTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** DisTimeTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** DisTimeTest tearDownClass()"); + // restore defaults + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + DisTime.setHostClockSynchronized(true); + DisTime.clearEpochLvc(); + } + + @Test + public void testDefaultTimestampStyle() + { + if (verbose) + System.out.println("*** DisTimeTest testDefaultTimestampStyle()"); + + assertEquals(TimestampStyle.IEEE_ABSOLUTE, DisTime.TIMESTAMP_STYLE_DEFAULT, "mismatched default timestamp style"); + } + + @Test + public void testSetGetTimestampStyle() + { + if (verbose) + System.out.println("*** DisTimeTest testSetGetTimestampStyle()"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_RELATIVE); + assertEquals(TimestampStyle.IEEE_RELATIVE, DisTime.getTimestampStyle(), "mismatched timestamp style after set"); + + DisTime.setTimestampStyle(TimestampStyle.UNIX); + assertEquals(TimestampStyle.UNIX, DisTime.getTimestampStyle(), "mismatched timestamp style after set to UNIX"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + } + + @Test + public void testHostClockSynchronized() + { + if (verbose) + System.out.println("*** DisTimeTest testHostClockSynchronized()"); + + DisTime.setHostClockSynchronized(true); + assertTrue(DisTime.isHostClockSynchronized(), "host clock should be synchronized"); + + DisTime.setHostClockSynchronized(false); + assertFalse(DisTime.isHostClockSynchronized(), "host clock should not be synchronized"); + + DisTime.setHostClockSynchronized(true); + } + + @Test + public void testGetCurrentDisTimestamp() + { + if (verbose) + System.out.println("*** DisTimeTest testGetCurrentDisTimestamp()"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + int timestamp = DisTime.getCurrentDisTimestamp(); + assertTrue(timestamp != 0, "IEEE_ABSOLUTE timestamp should not be zero"); + // absolute timestamps have LSB set to 1 + assertEquals(1, timestamp & DisTime.ABSOLUTE_TIMESTAMP_MASK, "absolute timestamp LSB should be 1"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_RELATIVE); + int relTimestamp = DisTime.getCurrentDisTimestamp(); + // relative timestamps have LSB set to 0 + assertEquals(0, relTimestamp & DisTime.ABSOLUTE_TIMESTAMP_MASK, "relative timestamp LSB should be 0"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + } + + @Test + public void testTimestampMasks() + { + if (verbose) + System.out.println("*** DisTimeTest testTimestampMasks()"); + + assertEquals(0x00000001, DisTime.ABSOLUTE_TIMESTAMP_MASK, "mismatched absolute timestamp mask"); + assertEquals(0xfffffffe, DisTime.RELATIVE_TIMESTAMP_MASK, "mismatched relative timestamp mask"); + } + + @Test + public void testEpochLvc() + { + if (verbose) + System.out.println("*** DisTimeTest testEpochLvc()"); + + DisTime.clearEpochLvc(); + assertFalse(DisTime.hasEpochLvc(), "epoch should not be active after clear"); + + DisTime.setEpochLvcNow(); + assertTrue(DisTime.hasEpochLvc(), "epoch should be active after setEpochLvcNow"); + assertNotNull(DisTime.getEpochLvc(), "epoch instant should not be null"); + + Instant custom = Instant.parse("2026-01-01T00:00:00Z"); + DisTime.setEpochLvc(custom); + assertEquals(custom, DisTime.getEpochLvc(), "mismatched custom epoch"); + + DisTime.clearEpochLvc(); + } + + @Test + public void testTimeFormatters() + { + if (verbose) + System.out.println("*** DisTimeTest testTimeFormatters()"); + + assertNotNull(DisTime.timeFormatterSeconds, "seconds formatter should not be null"); + assertNotNull(DisTime.timeFormatterTenthSeconds, "tenth seconds formatter should not be null"); + assertNotNull(DisTime.timeFormatterHundredthSeconds, "hundredth seconds formatter should not be null"); + assertNotNull(DisTime.timeFormatterMilliSeconds, "milliseconds formatter should not be null"); + assertNotNull(DisTime.timeFormatterMicroSeconds, "microseconds formatter should not be null"); + assertNotNull(DisTime.timeFormatterNanoSeconds, "nanoseconds formatter should not be null"); + } + + @Test + public void testSetTimeFormatter() + { + if (verbose) + System.out.println("*** DisTimeTest testSetTimeFormatter()"); + + DisTime.setTimeFormatter(TimeFormatterType.MILLISECONDS); + DateTimeFormatter formatter = DisTime.getTimeFormatter(); + assertNotNull(formatter, "formatter should not be null after set"); + + DisTime.setTimeFormatter(TimeFormatterType.TENTHSECONDS); + } + + @Test + public void testConvertToString() + { + if (verbose) + System.out.println("*** DisTimeTest testConvertToString()"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + int timestamp = DisTime.getCurrentDisTimestamp(); + String timeString = DisTime.convertToString(timestamp); + assertNotNull(timeString, "converted string should not be null"); + assertFalse(timeString.isEmpty(), "converted string should not be empty"); + + DisTime.setTimestampStyle(TimestampStyle.IEEE_ABSOLUTE); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("DisTimeTest start"); + DisTimeTest test = new DisTimeTest(); + setUpClass(); + test.testDefaultTimestampStyle(); + test.testSetGetTimestampStyle(); + test.testHostClockSynchronized(); + test.testGetCurrentDisTimestamp(); + test.testTimestampMasks(); + test.testEpochLvc(); + test.testTimeFormatters(); + test.testSetTimeFormatter(); + test.testConvertToString(); + tearDownClass(); + System.out.println("DisTimeTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/ElectromagneticEmissionPduTest.java b/test/edu/nps/moves/dis7/test/ElectromagneticEmissionPduTest.java new file mode 100644 index 0000000000..fa189f680b --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ElectromagneticEmissionPduTest.java @@ -0,0 +1,106 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ElectromagneticEmissionPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Electromagnetic Emission PDU fields and values. + */ +@DisplayName("ElectromagneticEmissionPduTest") +public class ElectromagneticEmissionPduTest extends PduTest +{ + /** default constructor */ + public ElectromagneticEmissionPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ElectromagneticEmissionPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ElectromagneticEmissionPduTest testMultiplePdus()"); + + ElectromagneticEmissionPdu emPdu = pduFactory.makeElectronicEmissionsPdu(); + + emPdu.setEmittingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + emPdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(emPdu); + + emPdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(emPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ElectromagneticEmissionPdu createdCast = (ElectromagneticEmissionPdu) createdPdu; + ElectromagneticEmissionPdu receivedCast = (ElectromagneticEmissionPdu) receivedPdus.get(0); + + assertEquals(createdCast.getEmittingEntityID(), receivedCast.getEmittingEntityID(), "mismatched EmittingEntityID"); + assertEquals(createdCast.getEventID(), receivedCast.getEventID(), "mismatched EventID"); + assertEquals(createdCast.getStateUpdateIndicator(), receivedCast.getStateUpdateIndicator(), "mismatched StateUpdateIndicator"); + assertEquals(createdCast.getSystems(), receivedCast.getSystems(), "mismatched Systems"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ElectromagneticEmissionPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityBodyCoordinatesTest.java b/test/edu/nps/moves/dis7/test/EntityBodyCoordinatesTest.java new file mode 100644 index 0000000000..dfc0d78283 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityBodyCoordinatesTest.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import SRM.*; +import edu.nps.moves.spatial.EntityBodyCoordinates; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EntityBodyCoordinates spatial utility class. + * Validates construction of body-centric lococentric Euclidean reference frames + * embedded in parent spatial reference frames with known Euler angles and identity rotations. + */ +@DisplayName("EntityBodyCoordinatesTest") +public class EntityBodyCoordinatesTest +{ + private static boolean verbose = true; + + /** A reusable parent LTSE reference frame */ + private static SRF_LocalTangentSpaceEuclidean parentSRF; + + /** default constructor */ + public EntityBodyCoordinatesTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest setUpClass()"); + + try + { + // Create a parent Local Tangent Space Euclidean SRF at equator/prime meridian + parentSRF = new SRF_LocalTangentSpaceEuclidean( + SRM_ORM_Code.ORMCOD_WGS_1984, + SRM_RT_Code.RTCOD_WGS_1984_IDENTITY, + 0.0, 0.0, // lon, lat in radians (equator/prime meridian) + 0.0, // azimuth + 0.0, 0.0, // false x, y origin + 0.0); // height offset + } + catch (SrmException e) + { + fail("Failed to create parent SRF: " + e); + } + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest tearDownClass()"); + } + + @Test + public void testConstructionWithIdentityAxes() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest testConstructionWithIdentityAxes()"); + + // Identity orientation: u axis along x (1,0,0), v axis along y (0,1,0) + // Origin at (0,0,0) in parent LTSE frame + EntityBodyCoordinates ebc = new EntityBodyCoordinates( + parentSRF, + 0.0f, 0.0f, 0.0f, // lococenter origin + 1.0f, 0.0f, 0.0f, // primary axis (u) along x + 0.0f, 1.0f, 0.0f); // secondary axis (v) along y + + assertNotNull(ebc, "EntityBodyCoordinates with identity axes should not be null"); + } + + @Test + public void testConstructionWithOffsetOrigin() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest testConstructionWithOffsetOrigin()"); + + // Place entity origin at (100, 200, 50) in parent frame + EntityBodyCoordinates ebc = new EntityBodyCoordinates( + parentSRF, + 100.0f, 200.0f, 50.0f, // lococenter offset from range origin + 1.0f, 0.0f, 0.0f, // primary axis (u) along x + 0.0f, 1.0f, 0.0f); // secondary axis (v) along y + + assertNotNull(ebc, "EntityBodyCoordinates with offset origin should not be null"); + } + + @Test + public void testConstructionWithRotatedAxes() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest testConstructionWithRotatedAxes()"); + + // Rotated 45 degrees: u axis along (cos45, sin45, 0), v axis along (-sin45, cos45, 0) + float cos45 = (float) Math.cos(Math.toRadians(45.0)); + float sin45 = (float) Math.sin(Math.toRadians(45.0)); + + EntityBodyCoordinates ebc = new EntityBodyCoordinates( + parentSRF, + 0.0f, 0.0f, 0.0f, // lococenter at origin + cos45, sin45, 0.0f, // primary axis (u) rotated 45 deg + -sin45, cos45, 0.0f); // secondary axis (v) perpendicular + + assertNotNull(ebc, "EntityBodyCoordinates with rotated axes should not be null"); + } + + @Test + public void testConstructionWithDifferentParentLocation() + { + if (verbose) + System.out.println("*** EntityBodyCoordinatesTest testConstructionWithDifferentParentLocation()"); + + try + { + // Create parent LTSE at Monterey area (36.6 lat, -121.9 lon) + SRF_LocalTangentSpaceEuclidean montereySRF = new SRF_LocalTangentSpaceEuclidean( + SRM_ORM_Code.ORMCOD_WGS_1984, + SRM_RT_Code.RTCOD_WGS_1984_IDENTITY, + Math.toRadians(-121.9), Math.toRadians(36.6), // lon, lat in radians + 0.0, // azimuth + 0.0, 0.0, // false x, y origin + 10.0); // height offset + + EntityBodyCoordinates ebc = new EntityBodyCoordinates( + montereySRF, + 500.0f, -300.0f, 25.0f, // lococenter offset + 1.0f, 0.0f, 0.0f, // primary axis (u) along x + 0.0f, 1.0f, 0.0f); // secondary axis (v) along y + + assertNotNull(ebc, "EntityBodyCoordinates at Monterey location should not be null"); + } + catch (SrmException e) + { + fail("Failed to create Monterey SRF: " + e); + } + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("EntityBodyCoordinatesTest start"); + EntityBodyCoordinatesTest test = new EntityBodyCoordinatesTest(); + setUpClass(); + test.testConstructionWithIdentityAxes(); + test.testConstructionWithOffsetOrigin(); + test.testConstructionWithRotatedAxes(); + test.testConstructionWithDifferentParentLocation(); + tearDownClass(); + System.out.println("EntityBodyCoordinatesTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityDamageStatusPduTest.java b/test/edu/nps/moves/dis7/test/EntityDamageStatusPduTest.java new file mode 100644 index 0000000000..34eef6ca5a --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityDamageStatusPduTest.java @@ -0,0 +1,103 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityDamageStatusPdu; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Entity Damage Status PDU fields and values. + */ +@DisplayName("EntityDamageStatusPduTest") +public class EntityDamageStatusPduTest extends PduTest +{ + /** default constructor */ + public EntityDamageStatusPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** EntityDamageStatusPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** EntityDamageStatusPduTest testMultiplePdus()"); + + EntityDamageStatusPdu edsPdu = pduFactory.makeEntityDamageStatusPdu(); + + edsPdu.setDamagedEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + testOnePdu(edsPdu); + + edsPdu.setDamagedEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + testOnePdu(edsPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + EntityDamageStatusPdu createdCast = (EntityDamageStatusPdu) createdPdu; + EntityDamageStatusPdu receivedCast = (EntityDamageStatusPdu) receivedPdus.get(0); + + assertEquals(createdCast.getDamagedEntityID(), receivedCast.getDamagedEntityID(), "mismatched DamagedEntityID"); + assertEquals(createdCast.getDamageDescriptionRecords(), receivedCast.getDamageDescriptionRecords(), "mismatched DamageDescriptionRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new EntityDamageStatusPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityIDTest.java b/test/edu/nps/moves/dis7/test/EntityIDTest.java new file mode 100644 index 0000000000..3ac71f7bf5 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityIDTest.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EntityID data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("EntityIDTest") +public class EntityIDTest +{ + private static boolean verbose = true; + + /** default constructor */ + public EntityIDTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EntityIDTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EntityIDTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** EntityIDTest testDefaultConstructor()"); + + EntityID id = new EntityID(); + assertEquals(0, id.getSiteID(), "mismatched default siteID"); + assertEquals(0, id.getApplicationID(), "mismatched default applicationID"); + assertEquals(0, id.getEntityID(), "mismatched default entityID"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** EntityIDTest testSettersAndGetters()"); + + EntityID id = new EntityID(); + id.setSiteID(1); + id.setApplicationID(2); + id.setEntityID(3); + assertEquals(1, id.getSiteID(), "mismatched siteID"); + assertEquals(2, id.getApplicationID(), "mismatched applicationID"); + assertEquals(3, id.getEntityID(), "mismatched entityID"); + } + + @Test + public void testProgressiveSetters() + { + if (verbose) + System.out.println("*** EntityIDTest testProgressiveSetters()"); + + EntityID id = new EntityID().setSiteID(10).setApplicationID(20).setEntityID(30); + assertEquals(10, id.getSiteID(), "mismatched siteID"); + assertEquals(20, id.getApplicationID(), "mismatched applicationID"); + assertEquals(30, id.getEntityID(), "mismatched entityID"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** EntityIDTest testMarshalledSize()"); + + EntityID id = new EntityID(); + assertEquals(6, id.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** EntityIDTest testMarshalUnmarshalDataStream()"); + + EntityID original = new EntityID(); + original.setSiteID(100); + original.setApplicationID(200); + original.setEntityID(300); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + EntityID restored = new EntityID(); + restored.unmarshal(dis); + + assertEquals(original.getSiteID(), restored.getSiteID(), "mismatched siteID after unmarshal"); + assertEquals(original.getApplicationID(), restored.getApplicationID(), "mismatched applicationID after unmarshal"); + assertEquals(original.getEntityID(), restored.getEntityID(), "mismatched entityID after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** EntityIDTest testMarshalUnmarshalByteBuffer()"); + + EntityID original = new EntityID(); + original.setSiteID(500); + original.setApplicationID(600); + original.setEntityID(700); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + EntityID restored = new EntityID(); + restored.unmarshal(buffer); + + assertEquals(original.getSiteID(), restored.getSiteID(), "mismatched siteID after ByteBuffer unmarshal"); + assertEquals(original.getApplicationID(), restored.getApplicationID(), "mismatched applicationID after ByteBuffer unmarshal"); + assertEquals(original.getEntityID(), restored.getEntityID(), "mismatched entityID after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** EntityIDTest testEquality()"); + + EntityID a = new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3); + EntityID b = new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3); + EntityID c = new EntityID().setSiteID(1).setApplicationID(2).setEntityID(4); + + assertTrue(a.equals(b), "equal EntityIDs should be equal"); + assertFalse(a.equals(c), "different EntityIDs should not be equal"); + assertEquals(a.hashCode(), b.hashCode(), "equal objects should have equal hashCodes"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("EntityIDTest start"); + EntityIDTest test = new EntityIDTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testProgressiveSetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("EntityIDTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityMarkingTest.java b/test/edu/nps/moves/dis7/test/EntityMarkingTest.java new file mode 100644 index 0000000000..eccdfb0b25 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityMarkingTest.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityMarking; +import edu.nps.moves.dis7.enumerations.EntityMarkingCharacterSet; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EntityMarking data structure. + * Validates construction, character encoding, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("EntityMarkingTest") +public class EntityMarkingTest +{ + private static boolean verbose = true; + + /** default constructor */ + public EntityMarkingTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EntityMarkingTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EntityMarkingTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** EntityMarkingTest testDefaultConstructor()"); + + EntityMarking em = new EntityMarking(); + assertNotNull(em.getCharacters(), "characters array should not be null"); + assertEquals(11, em.getCharacters().length, "characters array should be 11 bytes"); + } + + @Test + public void testSetCharacterSet() + { + if (verbose) + System.out.println("*** EntityMarkingTest testSetCharacterSet()"); + + EntityMarking em = new EntityMarking(); + em.setCharacterSet(EntityMarkingCharacterSet.ASCII); + assertEquals(EntityMarkingCharacterSet.ASCII, em.getCharacterSet(), "mismatched characterSet"); + } + + @Test + public void testSetCharacters() + { + if (verbose) + System.out.println("*** EntityMarkingTest testSetCharacters()"); + + EntityMarking em = new EntityMarking(); + em.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] marking = "TANK01".getBytes(); + byte[] padded = new byte[11]; + System.arraycopy(marking, 0, padded, 0, Math.min(marking.length, 11)); + em.setCharacters(padded); + + byte[] result = em.getCharacters(); + assertEquals((byte)'T', result[0], "mismatched character [0]"); + assertEquals((byte)'A', result[1], "mismatched character [1]"); + assertEquals((byte)'N', result[2], "mismatched character [2]"); + assertEquals((byte)'K', result[3], "mismatched character [3]"); + assertEquals((byte)'0', result[4], "mismatched character [4]"); + assertEquals((byte)'1', result[5], "mismatched character [5]"); + assertEquals(0, result[6], "padding should be zero"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** EntityMarkingTest testMarshalUnmarshalDataStream()"); + + EntityMarking original = new EntityMarking(); + original.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] marking = "F16EAGLE".getBytes(); + byte[] padded = new byte[11]; + System.arraycopy(marking, 0, padded, 0, Math.min(marking.length, 11)); + original.setCharacters(padded); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + EntityMarking restored = new EntityMarking(); + restored.unmarshal(dis); + + assertEquals(original.getCharacterSet(), restored.getCharacterSet(), "mismatched characterSet after unmarshal"); + assertArrayEquals(original.getCharacters(), restored.getCharacters(), "mismatched characters after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** EntityMarkingTest testMarshalUnmarshalByteBuffer()"); + + EntityMarking original = new EntityMarking(); + original.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] marking = "HELO99".getBytes(); + byte[] padded = new byte[11]; + System.arraycopy(marking, 0, padded, 0, Math.min(marking.length, 11)); + original.setCharacters(padded); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + EntityMarking restored = new EntityMarking(); + restored.unmarshal(buffer); + + assertEquals(original.getCharacterSet(), restored.getCharacterSet(), "mismatched characterSet after ByteBuffer unmarshal"); + assertArrayEquals(original.getCharacters(), restored.getCharacters(), "mismatched characters after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** EntityMarkingTest testEquality()"); + + EntityMarking a = new EntityMarking(); + a.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] m1 = new byte[11]; + m1[0] = (byte)'A'; + a.setCharacters(m1); + + EntityMarking b = new EntityMarking(); + b.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] m2 = new byte[11]; + m2[0] = (byte)'A'; + b.setCharacters(m2); + + EntityMarking c = new EntityMarking(); + c.setCharacterSet(EntityMarkingCharacterSet.ASCII); + byte[] m3 = new byte[11]; + m3[0] = (byte)'B'; + c.setCharacters(m3); + + assertTrue(a.equals(b), "equal EntityMarkings should be equal"); + assertFalse(a.equals(c), "different EntityMarkings should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("EntityMarkingTest start"); + EntityMarkingTest test = new EntityMarkingTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSetCharacterSet(); + test.testSetCharacters(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("EntityMarkingTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityStateUpdatePduTest.java b/test/edu/nps/moves/dis7/test/EntityStateUpdatePduTest.java new file mode 100644 index 0000000000..ef3eb92d89 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityStateUpdatePduTest.java @@ -0,0 +1,126 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EntityStateUpdatePdu; +import edu.nps.moves.dis7.pdus.EulerAngles; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Entity State Update PDU fields and values. + */ +@DisplayName("EntityStateUpdatePduTest") +public class EntityStateUpdatePduTest extends PduTest +{ + /** default constructor */ + public EntityStateUpdatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** EntityStateUpdatePduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** EntityStateUpdatePduTest testMultiplePdus()"); + + EntityStateUpdatePdu updatePdu = pduFactory.makeEntityStateUpdatePdu(); + + updatePdu.setEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + updatePdu.setEntityLinearVelocity(new Vector3Float().setX(10.0f).setY(20.0f).setZ(0.0f)); + updatePdu.setEntityLocation(new Vector3Double().setX(1000.0).setY(2000.0).setZ(3000.0)); + updatePdu.setEntityOrientation(new EulerAngles().setPsi(1.0f).setTheta(0.5f).setPhi(0.25f)); + updatePdu.setEntityAppearance(0x00010000); + testOnePdu(updatePdu); + + updatePdu.setEntityLinearVelocity(new Vector3Float().setX(15.0f).setY(25.0f).setZ(5.0f)); + updatePdu.setEntityLocation(new Vector3Double().setX(1100.0).setY(2100.0).setZ(3100.0)); + testOnePdu(updatePdu); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + EntityStateUpdatePdu createdUpdatePdu = (EntityStateUpdatePdu) createdPdu; + EntityStateUpdatePdu receivedUpdatePdu = (EntityStateUpdatePdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdUpdatePdu.getEntityID(), receivedUpdatePdu.getEntityID(), "mismatched EntityID"); + assertEquals(createdUpdatePdu.getEntityLinearVelocity(), receivedUpdatePdu.getEntityLinearVelocity(), "mismatched EntityLinearVelocity"); + assertEquals(createdUpdatePdu.getEntityLocation(), receivedUpdatePdu.getEntityLocation(), "mismatched EntityLocation"); + assertEquals(createdUpdatePdu.getEntityOrientation(), receivedUpdatePdu.getEntityOrientation(), "mismatched EntityOrientation"); + assertEquals(createdUpdatePdu.getEntityAppearance(), receivedUpdatePdu.getEntityAppearance(), "mismatched EntityAppearance"); + assertEquals(createdUpdatePdu.getVariableParameters(), receivedUpdatePdu.getVariableParameters(), "mismatched VariableParameters"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest entityStateUpdatePduTest = new EntityStateUpdatePduTest(); + + entityStateUpdatePduTest.setUp(); + entityStateUpdatePduTest.testMultiplePdus(); + entityStateUpdatePduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/EntityTypeTest.java b/test/edu/nps/moves/dis7/test/EntityTypeTest.java new file mode 100644 index 0000000000..25495dca2c --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EntityTypeTest.java @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.Country; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EntityType data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("EntityTypeTest") +public class EntityTypeTest +{ + private static boolean verbose = true; + + /** default constructor */ + public EntityTypeTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EntityTypeTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EntityTypeTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** EntityTypeTest testDefaultConstructor()"); + + EntityType et = new EntityType(); + assertEquals(0, et.getCategory(), "mismatched default category"); + assertEquals(0, et.getSubCategory(), "mismatched default subCategory"); + assertEquals(0, et.getSpecific(), "mismatched default specific"); + assertEquals(0, et.getExtra(), "mismatched default extra"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** EntityTypeTest testSettersAndGetters()"); + + EntityType et = new EntityType(); + et.setEntityKind(EntityKind.PLATFORM); + et.setCountry(Country.UNITED_STATES_OF_AMERICA_USA); + et.setCategory(1); + et.setSubCategory(2); + et.setSpecific(3); + et.setExtra(4); + + assertEquals(EntityKind.PLATFORM, et.getEntityKind(), "mismatched entityKind"); + assertEquals(Country.UNITED_STATES_OF_AMERICA_USA, et.getCountry(), "mismatched country"); + assertEquals(1, et.getCategory(), "mismatched category"); + assertEquals(2, et.getSubCategory(), "mismatched subCategory"); + assertEquals(3, et.getSpecific(), "mismatched specific"); + assertEquals(4, et.getExtra(), "mismatched extra"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** EntityTypeTest testMarshalUnmarshalDataStream()"); + + EntityType original = new EntityType(); + original.setEntityKind(EntityKind.PLATFORM); + original.setCountry(Country.UNITED_STATES_OF_AMERICA_USA); + original.setCategory(1); + original.setSubCategory(1); + original.setSpecific(2); + original.setExtra(0); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + EntityType restored = new EntityType(); + restored.unmarshal(dis); + + assertEquals(original.getEntityKind(), restored.getEntityKind(), "mismatched entityKind after unmarshal"); + assertEquals(original.getCountry(), restored.getCountry(), "mismatched country after unmarshal"); + assertEquals(original.getCategory(), restored.getCategory(), "mismatched category after unmarshal"); + assertEquals(original.getSubCategory(), restored.getSubCategory(), "mismatched subCategory after unmarshal"); + assertEquals(original.getSpecific(), restored.getSpecific(), "mismatched specific after unmarshal"); + assertEquals(original.getExtra(), restored.getExtra(), "mismatched extra after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** EntityTypeTest testMarshalUnmarshalByteBuffer()"); + + EntityType original = new EntityType(); + original.setEntityKind(EntityKind.MUNITION); + original.setCountry(Country.UNITED_STATES_OF_AMERICA_USA); + original.setCategory(2); + original.setSubCategory(3); + original.setSpecific(4); + original.setExtra(5); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + EntityType restored = new EntityType(); + restored.unmarshal(buffer); + + assertEquals(original.getEntityKind(), restored.getEntityKind(), "mismatched entityKind after ByteBuffer unmarshal"); + assertEquals(original.getCountry(), restored.getCountry(), "mismatched country after ByteBuffer unmarshal"); + assertEquals(original.getCategory(), restored.getCategory(), "mismatched category after ByteBuffer unmarshal"); + assertEquals(original.getSubCategory(), restored.getSubCategory(), "mismatched subCategory after ByteBuffer unmarshal"); + assertEquals(original.getSpecific(), restored.getSpecific(), "mismatched specific after ByteBuffer unmarshal"); + assertEquals(original.getExtra(), restored.getExtra(), "mismatched extra after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** EntityTypeTest testEquality()"); + + EntityType a = new EntityType(); + a.setEntityKind(EntityKind.PLATFORM); + a.setCategory(1); + a.setSubCategory(2); + EntityType b = new EntityType(); + b.setEntityKind(EntityKind.PLATFORM); + b.setCategory(1); + b.setSubCategory(2); + EntityType c = new EntityType(); + c.setEntityKind(EntityKind.MUNITION); + c.setCategory(1); + c.setSubCategory(2); + + assertTrue(a.equals(b), "equal EntityTypes should be equal"); + assertFalse(a.equals(c), "different EntityTypes should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("EntityTypeTest start"); + EntityTypeTest test = new EntityTypeTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("EntityTypeTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EnvironmentalProcessPduTest.java b/test/edu/nps/moves/dis7/test/EnvironmentalProcessPduTest.java new file mode 100644 index 0000000000..a7d30958ae --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EnvironmentalProcessPduTest.java @@ -0,0 +1,117 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.EnvironmentalProcessModelType; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.EnvironmentalProcessPdu; +import edu.nps.moves.dis7.pdus.ObjectIdentifier; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Environmental Process PDU fields and values. + */ +@DisplayName("EnvironmentalProcessPduTest") +public class EnvironmentalProcessPduTest extends PduTest +{ + /** default constructor */ + public EnvironmentalProcessPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** EnvironmentalProcessPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** EnvironmentalProcessPduTest testMultiplePdus()"); + + EnvironmentalProcessPdu epPdu = pduFactory.makeEnvironmentalProcessPdu(); + + epPdu.setEnvironementalProcessID(new ObjectIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + epPdu.setEnvironmentType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + epPdu.setModelType(EnvironmentalProcessModelType.NO_STATEMENT); + epPdu.setSequenceNumber((short) 1); + testOnePdu(epPdu); + + epPdu.setSequenceNumber((short) 2); + testOnePdu(epPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + EnvironmentalProcessPdu createdCast = (EnvironmentalProcessPdu) createdPdu; + EnvironmentalProcessPdu receivedCast = (EnvironmentalProcessPdu) receivedPdus.get(0); + + assertEquals(createdCast.getEnvironementalProcessID(), receivedCast.getEnvironementalProcessID(), "mismatched EnvironementalProcessID"); + assertEquals(createdCast.getEnvironmentType(), receivedCast.getEnvironmentType(), "mismatched EnvironmentType"); + assertEquals(createdCast.getModelType(), receivedCast.getModelType(), "mismatched ModelType"); + assertEquals(createdCast.getEnvironmentStatus(), receivedCast.getEnvironmentStatus(), "mismatched EnvironmentStatus"); + assertEquals(createdCast.getSequenceNumber(), receivedCast.getSequenceNumber(), "mismatched SequenceNumber"); + assertEquals(createdCast.getEnvironmentRecords(), receivedCast.getEnvironmentRecords(), "mismatched EnvironmentRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new EnvironmentalProcessPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/EulerAnglesTest.java b/test/edu/nps/moves/dis7/test/EulerAnglesTest.java new file mode 100644 index 0000000000..3130caaa57 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EulerAnglesTest.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EulerAngles; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EulerAngles data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and value ranges. + */ +@DisplayName("EulerAnglesTest") +public class EulerAnglesTest +{ + private static final float TOLERANCE = 1.0e-5f; + private static boolean verbose = true; + + /** default constructor */ + public EulerAnglesTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EulerAnglesTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EulerAnglesTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** EulerAnglesTest testDefaultConstructor()"); + + EulerAngles ea = new EulerAngles(); + assertEquals(0.0f, ea.getPsi(), TOLERANCE, "mismatched default psi"); + assertEquals(0.0f, ea.getTheta(), TOLERANCE, "mismatched default theta"); + assertEquals(0.0f, ea.getPhi(), TOLERANCE, "mismatched default phi"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** EulerAnglesTest testSettersAndGetters()"); + + EulerAngles ea = new EulerAngles(); + ea.setPsi(1.5f); + ea.setTheta(0.3f); + ea.setPhi(-0.7f); + assertEquals(1.5f, ea.getPsi(), TOLERANCE, "mismatched psi"); + assertEquals(0.3f, ea.getTheta(), TOLERANCE, "mismatched theta"); + assertEquals(-0.7f, ea.getPhi(), TOLERANCE, "mismatched phi"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** EulerAnglesTest testMarshalledSize()"); + + EulerAngles ea = new EulerAngles(); + assertEquals(12, ea.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** EulerAnglesTest testMarshalUnmarshalDataStream()"); + + EulerAngles original = new EulerAngles(); + original.setPsi((float) Math.PI); + original.setTheta((float)(Math.PI / 4.0)); + original.setPhi((float)(-Math.PI / 6.0)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + EulerAngles restored = new EulerAngles(); + restored.unmarshal(dis); + + assertEquals(original.getPsi(), restored.getPsi(), TOLERANCE, "mismatched psi after unmarshal"); + assertEquals(original.getTheta(), restored.getTheta(), TOLERANCE, "mismatched theta after unmarshal"); + assertEquals(original.getPhi(), restored.getPhi(), TOLERANCE, "mismatched phi after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** EulerAnglesTest testMarshalUnmarshalByteBuffer()"); + + EulerAngles original = new EulerAngles(); + original.setPsi(0.0f); + original.setTheta((float)(Math.PI / 2.0)); + original.setPhi((float) Math.PI); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + EulerAngles restored = new EulerAngles(); + restored.unmarshal(buffer); + + assertEquals(original.getPsi(), restored.getPsi(), TOLERANCE, "mismatched psi after ByteBuffer unmarshal"); + assertEquals(original.getTheta(), restored.getTheta(), TOLERANCE, "mismatched theta after ByteBuffer unmarshal"); + assertEquals(original.getPhi(), restored.getPhi(), TOLERANCE, "mismatched phi after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** EulerAnglesTest testEquality()"); + + EulerAngles a = new EulerAngles(); + a.setPsi(1.0f); + a.setTheta(2.0f); + a.setPhi(3.0f); + EulerAngles b = new EulerAngles(); + b.setPsi(1.0f); + b.setTheta(2.0f); + b.setPhi(3.0f); + EulerAngles c = new EulerAngles(); + c.setPsi(1.0f); + c.setTheta(2.0f); + c.setPhi(4.0f); + + assertTrue(a.equals(b), "equal EulerAngles should be equal"); + assertFalse(a.equals(c), "different EulerAngles should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("EulerAnglesTest start"); + EulerAnglesTest test = new EulerAnglesTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("EulerAnglesTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EulerConversionsTest.java b/test/edu/nps/moves/dis7/test/EulerConversionsTest.java new file mode 100644 index 0000000000..74edad505d --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EulerConversionsTest.java @@ -0,0 +1,345 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.CoordinateConversions; +import edu.nps.moves.dis7.utilities.EulerConversions; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EulerConversions utility class. + * Validates conversions between Tait-Bryan angles (heading/pitch/roll in degrees) + * and DIS Euler angles (psi/theta/phi in radians) given a geodetic position. + */ +@DisplayName("EulerConversionsTest") +public class EulerConversionsTest +{ + /** tolerance for angle round-trip in degrees */ + private static final double ANGLE_TOLERANCE_DEG = 0.001; + + /** tolerance for angle round-trip in radians */ + private static final double ANGLE_TOLERANCE_RAD = 0.00002; + + /** verbose output flag */ + private static boolean verbose = true; + + /** NPS Monterey latitude in radians */ + private static final double NPS_LAT_RAD = 36.5967 * CoordinateConversions.DEGREES_TO_RADIANS; + + /** NPS Monterey longitude in radians */ + private static final double NPS_LON_RAD = -121.8770 * CoordinateConversions.DEGREES_TO_RADIANS; + + /** default constructor */ + public EulerConversionsTest() + { + } + + /** preparation */ + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EulerConversionsTest setUpClass()"); + } + + /** cleanup */ + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EulerConversionsTest tearDownClass()"); + } + + /** + * Test round-trip: heading/pitch/roll -> psi/theta/phi -> heading/pitch/roll + * Entity heading north, level flight at NPS Monterey + */ + @Test + public void testRoundTripNorthLevel() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripNorthLevel()"); + + double yaw = 0.0; // north + double pitch = 0.0; // level + double roll = 0.0; // wings level + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (north, level)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (north, level)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (north, level)"); + } + + /** + * Test round-trip: heading east (90 degrees) + */ + @Test + public void testRoundTripEastHeading() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripEastHeading()"); + + double yaw = 90.0; // east + double pitch = 0.0; + double roll = 0.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (east)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (east)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (east)"); + } + + /** + * Test round-trip: heading south (180 degrees) + */ + @Test + public void testRoundTripSouthHeading() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripSouthHeading()"); + + double yaw = 180.0; + double pitch = 0.0; + double roll = 0.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (south)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (south)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (south)"); + } + + /** + * Test round-trip: heading west (-90 degrees) + */ + @Test + public void testRoundTripWestHeading() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripWestHeading()"); + + double yaw = -90.0; + double pitch = 0.0; + double roll = 0.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (west)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (west)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (west)"); + } + + /** + * Test round-trip: pitch up (30 degrees nose up), heading north + */ + @Test + public void testRoundTripPitchUp() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripPitchUp()"); + + double yaw = 0.0; + double pitch = 30.0; // nose up + double roll = 0.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (pitch up)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (pitch up)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (pitch up)"); + } + + /** + * Test round-trip: pitch down (-15 degrees nose down), heading east + */ + @Test + public void testRoundTripPitchDown() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripPitchDown()"); + + double yaw = 90.0; + double pitch = -15.0; // nose down + double roll = 0.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (pitch down)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (pitch down)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (pitch down)"); + } + + /** + * Test round-trip: banked turn (heading 45, roll 30) + */ + @Test + public void testRoundTripBankedTurn() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripBankedTurn()"); + + double yaw = 45.0; + double pitch = 0.0; + double roll = 30.0; // banked right + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (banked turn)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (banked turn)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (banked turn)"); + } + + /** + * Test round-trip: combined heading, pitch, and roll + * Heading 225 (southwest), pitch 10 up, roll -20 (left bank) + */ + @Test + public void testRoundTripCombinedAngles() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripCombinedAngles()"); + + double yaw = -135.0; // southwest (equivalent to 225 from north, but atan2 returns -135) + double pitch = 10.0; + double roll = -20.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(NPS_LAT_RAD, NPS_LON_RAD, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(NPS_LAT_RAD, NPS_LON_RAD, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading after round-trip (combined)"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch after round-trip (combined)"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll after round-trip (combined)"); + } + + /** + * Test at equator/prime meridian (lat=0, lon=0) to verify different position + */ + @Test + public void testRoundTripEquator() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripEquator()"); + + double lat = 0.0; + double lon = 0.0; + double yaw = 45.0; + double pitch = 10.0; + double roll = 5.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(lat, lon, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(lat, lon, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(lat, lon, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(lat, lon, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(lat, lon, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(lat, lon, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading at equator"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch at equator"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll at equator"); + } + + /** + * Test at southern hemisphere position: Cape Town (-33.9, 18.4) + */ + @Test + public void testRoundTripSouthernHemisphere() + { + if (verbose) + System.out.println("*** EulerConversionsTest testRoundTripSouthernHemisphere()"); + + double lat = -33.9 * CoordinateConversions.DEGREES_TO_RADIANS; + double lon = 18.4 * CoordinateConversions.DEGREES_TO_RADIANS; + double yaw = 60.0; + double pitch = 5.0; + double roll = -10.0; + + double psi = EulerConversions.getPsiFromTaitBryanAngles(lat, lon, yaw, pitch); + double theta = EulerConversions.getThetaFromTaitBryanAngles(lat, lon, yaw, pitch); + double phi = EulerConversions.getPhiFromTaitBryanAngles(lat, lon, yaw, pitch, roll); + + double headingBack = EulerConversions.getOrientationFromEuler(lat, lon, psi, theta); + double pitchBack = EulerConversions.getPitchFromEuler(lat, lon, psi, theta); + double rollBack = EulerConversions.getRollFromEuler(lat, lon, psi, theta, phi); + + assertEquals(yaw, headingBack, ANGLE_TOLERANCE_DEG, "mismatched heading at southern hemisphere"); + assertEquals(pitch, pitchBack, ANGLE_TOLERANCE_DEG, "mismatched pitch at southern hemisphere"); + assertEquals(roll, rollBack, ANGLE_TOLERANCE_DEG, "mismatched roll at southern hemisphere"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("EulerConversionsTest start"); + EulerConversionsTest test = new EulerConversionsTest(); + + setUpClass(); + test.testRoundTripNorthLevel(); + test.testRoundTripEastHeading(); + test.testRoundTripSouthHeading(); + test.testRoundTripWestHeading(); + test.testRoundTripPitchUp(); + test.testRoundTripPitchDown(); + test.testRoundTripBankedTurn(); + test.testRoundTripCombinedAngles(); + test.testRoundTripEquator(); + test.testRoundTripSouthernHemisphere(); + tearDownClass(); + + System.out.println("EulerConversionsTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EventIdentifierTest.java b/test/edu/nps/moves/dis7/test/EventIdentifierTest.java new file mode 100644 index 0000000000..d43dd66fcd --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EventIdentifierTest.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EventIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for EventIdentifier data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("EventIdentifierTest") +public class EventIdentifierTest +{ + private static boolean verbose = true; + + /** default constructor */ + public EventIdentifierTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** EventIdentifierTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** EventIdentifierTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** EventIdentifierTest testDefaultConstructor()"); + + EventIdentifier ei = new EventIdentifier(); + assertNotNull(ei.getSimulationAddress(), "simulationAddress should not be null"); + assertEquals(0, ei.getEventNumber(), "mismatched default eventNumber"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** EventIdentifierTest testSettersAndGetters()"); + + EventIdentifier ei = new EventIdentifier(); + SimulationAddress sa = new SimulationAddress(); + sa.setSite(10); + sa.setApplication(20); + ei.setSimulationAddress(sa); + ei.setEventNumber(42); + + assertEquals(10, ei.getSimulationAddress().getSite(), "mismatched site"); + assertEquals(20, ei.getSimulationAddress().getApplication(), "mismatched application"); + assertEquals(42, ei.getEventNumber(), "mismatched eventNumber"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** EventIdentifierTest testMarshalledSize()"); + + EventIdentifier ei = new EventIdentifier(); + assertEquals(6, ei.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** EventIdentifierTest testMarshalUnmarshalDataStream()"); + + EventIdentifier original = new EventIdentifier(); + original.getSimulationAddress().setSite(100); + original.getSimulationAddress().setApplication(200); + original.setEventNumber(300); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + EventIdentifier restored = new EventIdentifier(); + restored.unmarshal(dis); + + assertEquals(original.getSimulationAddress().getSite(), restored.getSimulationAddress().getSite(), "mismatched site after unmarshal"); + assertEquals(original.getSimulationAddress().getApplication(), restored.getSimulationAddress().getApplication(), "mismatched application after unmarshal"); + assertEquals(original.getEventNumber(), restored.getEventNumber(), "mismatched eventNumber after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** EventIdentifierTest testMarshalUnmarshalByteBuffer()"); + + EventIdentifier original = new EventIdentifier(); + original.getSimulationAddress().setSite(500); + original.getSimulationAddress().setApplication(600); + original.setEventNumber(700); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + EventIdentifier restored = new EventIdentifier(); + restored.unmarshal(buffer); + + assertEquals(original.getSimulationAddress().getSite(), restored.getSimulationAddress().getSite(), "mismatched site after ByteBuffer unmarshal"); + assertEquals(original.getSimulationAddress().getApplication(), restored.getSimulationAddress().getApplication(), "mismatched application after ByteBuffer unmarshal"); + assertEquals(original.getEventNumber(), restored.getEventNumber(), "mismatched eventNumber after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** EventIdentifierTest testEquality()"); + + EventIdentifier a = new EventIdentifier(); + a.getSimulationAddress().setSite(1); + a.getSimulationAddress().setApplication(2); + a.setEventNumber(3); + + EventIdentifier b = new EventIdentifier(); + b.getSimulationAddress().setSite(1); + b.getSimulationAddress().setApplication(2); + b.setEventNumber(3); + + EventIdentifier c = new EventIdentifier(); + c.getSimulationAddress().setSite(1); + c.getSimulationAddress().setApplication(2); + c.setEventNumber(4); + + assertTrue(a.equals(b), "equal EventIdentifiers should be equal"); + assertFalse(a.equals(c), "different EventIdentifiers should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("EventIdentifierTest start"); + EventIdentifierTest test = new EventIdentifierTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("EventIdentifierTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/EventReportPduTest.java b/test/edu/nps/moves/dis7/test/EventReportPduTest.java new file mode 100644 index 0000000000..6721af3ab5 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EventReportPduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EventReportPdu; +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.VariableRecordType; + +/** + * Unit tests for satisfactory handling of Event Report PDU fields and values. + */ +@DisplayName("EventReportPduTest") +public class EventReportPduTest extends PduTest +{ + /** default constructor */ + public EventReportPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** EventReportPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** EventReportPduTest testMultiplePdus()"); + + EventReportPdu eventReportPdu = pduFactory.makeEventReportPdu(); + + eventReportPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + eventReportPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + eventReportPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(88)); + eventReportPdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST).setVariableDatumValue(new byte[]{1, 2, 3, 4, 5, 6, 7, 8})); + testOnePdu(eventReportPdu); + + eventReportPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(99)); + testOnePdu(eventReportPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + EventReportPdu createdCast = (EventReportPdu) createdPdu; + EventReportPdu receivedCast = (EventReportPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getEventType(), receivedCast.getEventType(), "mismatched EventType"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new EventReportPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/EventReportReliablePduTest.java b/test/edu/nps/moves/dis7/test/EventReportReliablePduTest.java new file mode 100644 index 0000000000..a941d648fc --- /dev/null +++ b/test/edu/nps/moves/dis7/test/EventReportReliablePduTest.java @@ -0,0 +1,110 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.EventReportEventType; +import edu.nps.moves.dis7.pdus.EventReportReliablePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Event Report Reliable PDU fields and values. + */ +@DisplayName("EventReportReliablePduTest") +public class EventReportReliablePduTest extends PduTest +{ + /** default constructor */ + public EventReportReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** EventReportReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** EventReportReliablePduTest testMultiplePdus()"); + + EventReportReliablePdu errPdu = pduFactory.makeEventReportReliablePdu(); + + errPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + errPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + errPdu.setEventType(EventReportEventType.OTHER); + testOnePdu(errPdu); + + errPdu.setEventType(EventReportEventType.RAN_OUT_OF_AMMUNITION); + testOnePdu(errPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + EventReportReliablePdu createdCast = (EventReportReliablePdu) createdPdu; + EventReportReliablePdu receivedCast = (EventReportReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getEventType(), receivedCast.getEventType(), "mismatched EventType"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new EventReportReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/FixedDatumTest.java b/test/edu/nps/moves/dis7/test/FixedDatumTest.java new file mode 100644 index 0000000000..a4256728bc --- /dev/null +++ b/test/edu/nps/moves/dis7/test/FixedDatumTest.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.enumerations.VariableRecordType; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for FixedDatum data structure. + * Validates construction, field access, and marshal/unmarshal round-trip. + */ +@DisplayName("FixedDatumTest") +public class FixedDatumTest +{ + private static boolean verbose = true; + + /** default constructor */ + public FixedDatumTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** FixedDatumTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** FixedDatumTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** FixedDatumTest testDefaultConstructor()"); + + FixedDatum fd = new FixedDatum(); + assertEquals(0, fd.getFixedDatumValue(), "mismatched default fixedDatumValue"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** FixedDatumTest testSettersAndGetters()"); + + FixedDatum fd = new FixedDatum(); + fd.setFixedDatumValue(12345); + assertEquals(12345, fd.getFixedDatumValue(), "mismatched fixedDatumValue"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** FixedDatumTest testMarshalledSize()"); + + FixedDatum fd = new FixedDatum(); + assertEquals(8, fd.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** FixedDatumTest testMarshalUnmarshalDataStream()"); + + FixedDatum original = new FixedDatum(); + original.setFixedDatumValue(99999); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + FixedDatum restored = new FixedDatum(); + restored.unmarshal(dis); + + assertEquals(original.getFixedDatumValue(), restored.getFixedDatumValue(), "mismatched fixedDatumValue after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** FixedDatumTest testMarshalUnmarshalByteBuffer()"); + + FixedDatum original = new FixedDatum(); + original.setFixedDatumValue(77777); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + FixedDatum restored = new FixedDatum(); + restored.unmarshal(buffer); + + assertEquals(original.getFixedDatumValue(), restored.getFixedDatumValue(), "mismatched fixedDatumValue after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** FixedDatumTest testEquality()"); + + FixedDatum a = new FixedDatum(); + a.setFixedDatumValue(100); + FixedDatum b = new FixedDatum(); + b.setFixedDatumValue(100); + FixedDatum c = new FixedDatum(); + c.setFixedDatumValue(200); + + assertTrue(a.equals(b), "equal FixedDatums should be equal"); + assertFalse(a.equals(c), "different FixedDatums should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("FixedDatumTest start"); + FixedDatumTest test = new FixedDatumTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("FixedDatumTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/GriddedDataPduTest.java b/test/edu/nps/moves/dis7/test/GriddedDataPduTest.java new file mode 100644 index 0000000000..bdd25ec082 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/GriddedDataPduTest.java @@ -0,0 +1,130 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.GriddedDataCoordinateSystem; +import edu.nps.moves.dis7.enumerations.GriddedDataConstantGrid; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.GriddedDataPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Gridded Data PDU fields and values. + */ +@DisplayName("GriddedDataPduTest") +public class GriddedDataPduTest extends PduTest +{ + /** default constructor */ + public GriddedDataPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** GriddedDataPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** GriddedDataPduTest testMultiplePdus()"); + + GriddedDataPdu gdPdu = pduFactory.makeGriddedDataPdu(); + + gdPdu.setEnvironmentalSimulationApplicationID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + gdPdu.setFieldNumber((short) 1); + gdPdu.setPduNumber((short) 1); + gdPdu.setPduTotal((short) 1); + gdPdu.setCoordinateSystem(GriddedDataCoordinateSystem.RIGHT_HANDED_CARTESIAN_LOCAL_TOPOGRAPHIC_PROJECTION_EAST_NORTH_UP); + gdPdu.setConstantGrid(GriddedDataConstantGrid.CONSTANT_GRID); + gdPdu.setEnvironmentType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + testOnePdu(gdPdu); + + gdPdu.setFieldNumber((short) 2); + gdPdu.setCoordinateSystem(GriddedDataCoordinateSystem.LATITUDE_LONGITUDE_HEIGHT); + gdPdu.setConstantGrid(GriddedDataConstantGrid.UPDATED_GRID); + testOnePdu(gdPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + GriddedDataPdu createdCast = (GriddedDataPdu) createdPdu; + GriddedDataPdu receivedCast = (GriddedDataPdu) receivedPdus.get(0); + + assertEquals(createdCast.getEnvironmentalSimulationApplicationID(), receivedCast.getEnvironmentalSimulationApplicationID(), "mismatched EnvironmentalSimulationApplicationID"); + assertEquals(createdCast.getFieldNumber(), receivedCast.getFieldNumber(), "mismatched FieldNumber"); + assertEquals(createdCast.getPduNumber(), receivedCast.getPduNumber(), "mismatched PduNumber"); + assertEquals(createdCast.getPduTotal(), receivedCast.getPduTotal(), "mismatched PduTotal"); + assertEquals(createdCast.getCoordinateSystem(), receivedCast.getCoordinateSystem(), "mismatched CoordinateSystem"); + assertEquals(createdCast.getConstantGrid(), receivedCast.getConstantGrid(), "mismatched ConstantGrid"); + assertEquals(createdCast.getEnvironmentType(), receivedCast.getEnvironmentType(), "mismatched EnvironmentType"); + assertEquals(createdCast.getOrientation(), receivedCast.getOrientation(), "mismatched Orientation"); + assertEquals(createdCast.getSampleTime(), receivedCast.getSampleTime(), "mismatched SampleTime"); + assertEquals(createdCast.getTotalValues(), receivedCast.getTotalValues(), "mismatched TotalValues"); + assertEquals(createdCast.getVectorDimension(), receivedCast.getVectorDimension(), "mismatched VectorDimension"); + assertEquals(createdCast.getGridAxisDescriptors(), receivedCast.getGridAxisDescriptors(), "mismatched GridAxisDescriptors"); + assertEquals(createdCast.getGridDataRecords(), receivedCast.getGridDataRecords(), "mismatched GridDataRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new GriddedDataPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/InformationOperationsActionPduTest.java b/test/edu/nps/moves/dis7/test/InformationOperationsActionPduTest.java new file mode 100644 index 0000000000..53add68cfb --- /dev/null +++ b/test/edu/nps/moves/dis7/test/InformationOperationsActionPduTest.java @@ -0,0 +1,121 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.IOActionIOActionPhase; +import edu.nps.moves.dis7.enumerations.IOActionIOActionType; +import edu.nps.moves.dis7.enumerations.IOActionIOWarfareType; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.InformationOperationsActionPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Information Operations Action PDU fields and values. + */ +@DisplayName("InformationOperationsActionPduTest") +public class InformationOperationsActionPduTest extends PduTest +{ + /** default constructor */ + public InformationOperationsActionPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** InformationOperationsActionPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** InformationOperationsActionPduTest testMultiplePdus()"); + + InformationOperationsActionPdu ioaPdu = pduFactory.makeInformationOperationsActionPdu(); + + ioaPdu.setOriginatingSimID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + ioaPdu.setReceivingSimID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + ioaPdu.setIoAttackerID(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + ioaPdu.setIoPrimaryTargetID(new EntityID().setSiteID(10).setApplicationID(11).setEntityID(12)); + ioaPdu.setRequestID(101); + ioaPdu.setIOWarfareType(IOActionIOWarfareType.ELECTRONIC_WARFARE_EW); + ioaPdu.setIOActionType(IOActionIOActionType.NO_STATEMENT); + ioaPdu.setIOActionPhase(IOActionIOActionPhase.START_ATTACK_PROFILE); + testOnePdu(ioaPdu); + + ioaPdu.setRequestID(102); + ioaPdu.setIOActionPhase(IOActionIOActionPhase.END_ATTACK_PROFILE); + testOnePdu(ioaPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + InformationOperationsActionPdu createdCast = (InformationOperationsActionPdu) createdPdu; + InformationOperationsActionPdu receivedCast = (InformationOperationsActionPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingSimID(), receivedCast.getOriginatingSimID(), "mismatched OriginatingSimID"); + assertEquals(createdCast.getReceivingSimID(), receivedCast.getReceivingSimID(), "mismatched ReceivingSimID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getIOWarfareType(), receivedCast.getIOWarfareType(), "mismatched IOWarfareType"); + assertEquals(createdCast.getIOActionType(), receivedCast.getIOActionType(), "mismatched IOActionType"); + assertEquals(createdCast.getIOActionPhase(), receivedCast.getIOActionPhase(), "mismatched IOActionPhase"); + assertEquals(createdCast.getIoAttackerID(), receivedCast.getIoAttackerID(), "mismatched IoAttackerID"); + assertEquals(createdCast.getIoPrimaryTargetID(), receivedCast.getIoPrimaryTargetID(), "mismatched IoPrimaryTargetID"); + assertEquals(createdCast.getIoRecords(), receivedCast.getIoRecords(), "mismatched IoRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new InformationOperationsActionPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/InformationOperationsReportPduTest.java b/test/edu/nps/moves/dis7/test/InformationOperationsReportPduTest.java new file mode 100644 index 0000000000..cee82a6ef2 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/InformationOperationsReportPduTest.java @@ -0,0 +1,111 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.IOReportIOReportType; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.InformationOperationsReportPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Information Operations Report PDU fields and values. + */ +@DisplayName("InformationOperationsReportPduTest") +public class InformationOperationsReportPduTest extends PduTest +{ + /** default constructor */ + public InformationOperationsReportPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** InformationOperationsReportPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** InformationOperationsReportPduTest testMultiplePdus()"); + + InformationOperationsReportPdu iorPdu = pduFactory.makeInformationOperationsReportPdu(); + + iorPdu.setOriginatingSimID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + iorPdu.setIoAttackerID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + iorPdu.setIoPrimaryTargetID(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + iorPdu.setIoReportType(IOReportIOReportType.INITIAL_REPORT); + testOnePdu(iorPdu); + + iorPdu.setIoReportType(IOReportIOReportType.UPDATE_REPORT); + testOnePdu(iorPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + InformationOperationsReportPdu createdCast = (InformationOperationsReportPdu) createdPdu; + InformationOperationsReportPdu receivedCast = (InformationOperationsReportPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingSimID(), receivedCast.getOriginatingSimID(), "mismatched OriginatingSimID"); + assertEquals(createdCast.getIoSimSource(), receivedCast.getIoSimSource(), "mismatched IoSimSource"); + assertEquals(createdCast.getIoReportType(), receivedCast.getIoReportType(), "mismatched IoReportType"); + assertEquals(createdCast.getIoAttackerID(), receivedCast.getIoAttackerID(), "mismatched IoAttackerID"); + assertEquals(createdCast.getIoPrimaryTargetID(), receivedCast.getIoPrimaryTargetID(), "mismatched IoPrimaryTargetID"); + assertEquals(createdCast.getIoRecords(), receivedCast.getIoRecords(), "mismatched IoRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new InformationOperationsReportPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/IntercomControlPduTest.java b/test/edu/nps/moves/dis7/test/IntercomControlPduTest.java new file mode 100644 index 0000000000..b5bfb693c4 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/IntercomControlPduTest.java @@ -0,0 +1,117 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.IntercomControlControlType; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.IntercomControlPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Intercom Control PDU fields and values. + */ +@DisplayName("IntercomControlPduTest") +public class IntercomControlPduTest extends PduTest +{ + /** default constructor */ + public IntercomControlPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** IntercomControlPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** IntercomControlPduTest testMultiplePdus()"); + + IntercomControlPdu intercomControlPdu = pduFactory.makeIntercomControlPdu(); + + intercomControlPdu.setControlType(IntercomControlControlType.STATUS); + intercomControlPdu.setSourceEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + intercomControlPdu.setSourceIntercomNumber((short) 1); + intercomControlPdu.setMasterIntercomReferenceID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + intercomControlPdu.setMasterIntercomNumber((short) 10); + intercomControlPdu.setMasterChannelID((short) 1); + testOnePdu(intercomControlPdu); + + intercomControlPdu.setControlType(IntercomControlControlType.REQUEST_ACKNOWLEDGE_REQUIRED); + testOnePdu(intercomControlPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + IntercomControlPdu createdCast = (IntercomControlPdu) createdPdu; + IntercomControlPdu receivedCast = (IntercomControlPdu) receivedPdus.get(0); + + assertEquals(createdCast.getControlType(), receivedCast.getControlType(), "mismatched ControlType"); + assertEquals(createdCast.getCommunicationsChannelType(), receivedCast.getCommunicationsChannelType(), "mismatched CommunicationsChannelType"); + assertEquals(createdCast.getSourceEntityID(), receivedCast.getSourceEntityID(), "mismatched SourceEntityID"); + assertEquals(createdCast.getSourceIntercomNumber(), receivedCast.getSourceIntercomNumber(), "mismatched SourceIntercomNumber"); + assertEquals(createdCast.getTransmitLineState(), receivedCast.getTransmitLineState(), "mismatched TransmitLineState"); + assertEquals(createdCast.getCommand(), receivedCast.getCommand(), "mismatched Command"); + assertEquals(createdCast.getMasterIntercomReferenceID(), receivedCast.getMasterIntercomReferenceID(), "mismatched MasterIntercomReferenceID"); + assertEquals(createdCast.getMasterIntercomNumber(), receivedCast.getMasterIntercomNumber(), "mismatched MasterIntercomNumber"); + assertEquals(createdCast.getMasterChannelID(), receivedCast.getMasterChannelID(), "mismatched MasterChannelID"); + assertEquals(createdCast.getIntercomParameters(), receivedCast.getIntercomParameters(), "mismatched IntercomParameters"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new IntercomControlPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/IntercomSignalPduTest.java b/test/edu/nps/moves/dis7/test/IntercomSignalPduTest.java new file mode 100644 index 0000000000..fa12551111 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/IntercomSignalPduTest.java @@ -0,0 +1,112 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.IntercomSignalPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Intercom Signal PDU fields and values. + */ +@DisplayName("IntercomSignalPduTest") +public class IntercomSignalPduTest extends PduTest +{ + /** default constructor */ + public IntercomSignalPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** IntercomSignalPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** IntercomSignalPduTest testMultiplePdus()"); + + IntercomSignalPdu intercomSignalPdu = pduFactory.makeIntercomSignalPdu(); + + intercomSignalPdu.setIntercomNumber((short) 1); + intercomSignalPdu.setEncodingScheme((short) 1); + intercomSignalPdu.setSampleRate(8000); + intercomSignalPdu.setData(new byte[]{10, 20, 30, 40, 50, 60, 70, 80}); + intercomSignalPdu.setDataLength((short) 64); // 8 bytes * 8 bits + testOnePdu(intercomSignalPdu); + + intercomSignalPdu.setSampleRate(16000); + testOnePdu(intercomSignalPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + IntercomSignalPdu createdCast = (IntercomSignalPdu) createdPdu; + IntercomSignalPdu receivedCast = (IntercomSignalPdu) receivedPdus.get(0); + + assertEquals(createdCast.getIntercomReferenceID(), receivedCast.getIntercomReferenceID(), "mismatched IntercomReferenceID"); + assertEquals(createdCast.getIntercomNumber(), receivedCast.getIntercomNumber(), "mismatched IntercomNumber"); + assertEquals(createdCast.getEncodingScheme(), receivedCast.getEncodingScheme(), "mismatched EncodingScheme"); + assertEquals(createdCast.getTdlType(), receivedCast.getTdlType(), "mismatched TdlType"); + assertEquals(createdCast.getSampleRate(), receivedCast.getSampleRate(), "mismatched SampleRate"); + assertEquals(createdCast.getDataLength(), receivedCast.getDataLength(), "mismatched DataLength"); + assertEquals(createdCast.getSamples(), receivedCast.getSamples(), "mismatched Samples"); + assertArrayEquals(createdCast.getData(), receivedCast.getData(), "mismatched Data"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new IntercomSignalPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/IsGroupOfPduTest.java b/test/edu/nps/moves/dis7/test/IsGroupOfPduTest.java new file mode 100644 index 0000000000..f2ec5dedc8 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/IsGroupOfPduTest.java @@ -0,0 +1,112 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.IsGroupOfGroupedEntityCategory; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.IsGroupOfPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of IsGroupOf PDU fields and values. + */ +@DisplayName("IsGroupOfPduTest") +public class IsGroupOfPduTest extends PduTest +{ + /** default constructor */ + public IsGroupOfPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** IsGroupOfPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** IsGroupOfPduTest testMultiplePdus()"); + + IsGroupOfPdu igoPdu = pduFactory.makeIsGroupOfPdu(); + + igoPdu.setGroupEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + igoPdu.setGroupedEntityCategory(IsGroupOfGroupedEntityCategory.UNDEFINED); + igoPdu.setLatitude(36.595); + igoPdu.setLongitude(-121.877); + testOnePdu(igoPdu); + + igoPdu.setGroupedEntityCategory(IsGroupOfGroupedEntityCategory.BASIC_GROUND_COMBAT_VEHICLE); + igoPdu.setLatitude(37.0); + igoPdu.setLongitude(-122.0); + testOnePdu(igoPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + IsGroupOfPdu createdCast = (IsGroupOfPdu) createdPdu; + IsGroupOfPdu receivedCast = (IsGroupOfPdu) receivedPdus.get(0); + + assertEquals(createdCast.getGroupEntityID(), receivedCast.getGroupEntityID(), "mismatched GroupEntityID"); + assertEquals(createdCast.getGroupedEntityCategory(), receivedCast.getGroupedEntityCategory(), "mismatched GroupedEntityCategory"); + assertEquals(createdCast.getLatitude(), receivedCast.getLatitude(), "mismatched Latitude"); + assertEquals(createdCast.getLongitude(), receivedCast.getLongitude(), "mismatched Longitude"); + assertEquals(createdCast.getGroupedEntityDescriptions(), receivedCast.getGroupedEntityDescriptions(), "mismatched GroupedEntityDescriptions"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new IsGroupOfPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/IsPartOfPduTest.java b/test/edu/nps/moves/dis7/test/IsPartOfPduTest.java new file mode 100644 index 0000000000..82d28e233a --- /dev/null +++ b/test/edu/nps/moves/dis7/test/IsPartOfPduTest.java @@ -0,0 +1,116 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.IsPartOfPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of IsPartOf PDU fields and values. + */ +@DisplayName("IsPartOfPduTest") +public class IsPartOfPduTest extends PduTest +{ + /** default constructor */ + public IsPartOfPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** IsPartOfPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** IsPartOfPduTest testMultiplePdus()"); + + IsPartOfPdu ipoPdu = pduFactory.makeIsPartOfPdu(); + + ipoPdu.setOrginatingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + ipoPdu.setReceivingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + ipoPdu.setPartLocation(new Vector3Float().setX(10.0f).setY(20.0f).setZ(5.0f)); + ipoPdu.setPartEntityType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA).setCategory((byte) 1)); + testOnePdu(ipoPdu); + + ipoPdu.setPartLocation(new Vector3Float().setX(30.0f).setY(40.0f).setZ(15.0f)); + testOnePdu(ipoPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + IsPartOfPdu createdCast = (IsPartOfPdu) createdPdu; + IsPartOfPdu receivedCast = (IsPartOfPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOrginatingEntityID(), receivedCast.getOrginatingEntityID(), "mismatched OrginatingEntityID"); + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getRelationship(), receivedCast.getRelationship(), "mismatched Relationship"); + assertEquals(createdCast.getPartLocation(), receivedCast.getPartLocation(), "mismatched PartLocation"); + assertEquals(createdCast.getNamedLocationID(), receivedCast.getNamedLocationID(), "mismatched NamedLocationID"); + assertEquals(createdCast.getPartEntityType(), receivedCast.getPartEntityType(), "mismatched PartEntityType"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new IsPartOfPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/Issue09Unresolved.java b/test/edu/nps/moves/dis7/test/Issue09Unresolved.java index 81b9c340a1..ca267ffa3c 100644 --- a/test/edu/nps/moves/dis7/test/Issue09Unresolved.java +++ b/test/edu/nps/moves/dis7/test/Issue09Unresolved.java @@ -44,6 +44,7 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import edu.nps.moves.dis7.enumerations.PlatformDomain; /** EntityType is instantiated with a default Domain of PlatformDomain-OTHER * which causes issues down the road with similar enum values of other Domain diff --git a/test/edu/nps/moves/dis7/test/LinearObjectStatePduTest.java b/test/edu/nps/moves/dis7/test/LinearObjectStatePduTest.java new file mode 100644 index 0000000000..648ccbef83 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/LinearObjectStatePduTest.java @@ -0,0 +1,120 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.LinearObjectStatePdu; +import edu.nps.moves.dis7.pdus.ObjectIdentifier; +import edu.nps.moves.dis7.pdus.ObjectType; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.ObjectKind; + +/** + * Unit tests for satisfactory handling of Linear Object State PDU fields and values. + */ +@DisplayName("LinearObjectStatePduTest") +public class LinearObjectStatePduTest extends PduTest +{ + /** default constructor */ + public LinearObjectStatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** LinearObjectStatePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** LinearObjectStatePduTest testMultiplePdus()"); + + LinearObjectStatePdu losPdu = pduFactory.makeLinearObjectStatePdu(); + + losPdu.setObjectID(new ObjectIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + losPdu.setForceID(ForceID.FRIENDLY); + losPdu.setObjectType(new ObjectType().setDomain(PlatformDomain.LAND).setObjectKind(ObjectKind.OBSTACLE).setCategory((byte) 2)); + losPdu.setRequesterID(new SimulationAddress().setSite(1).setApplication(2)); + losPdu.setReceivingID(new SimulationAddress().setSite(3).setApplication(4)); + losPdu.setUpdateNumber((short) 1); + testOnePdu(losPdu); + + losPdu.setUpdateNumber((short) 2); + losPdu.setForceID(ForceID.OPPOSING); + testOnePdu(losPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + LinearObjectStatePdu createdCast = (LinearObjectStatePdu) createdPdu; + LinearObjectStatePdu receivedCast = (LinearObjectStatePdu) receivedPdus.get(0); + + assertEquals(createdCast.getObjectID(), receivedCast.getObjectID(), "mismatched ObjectID"); + assertEquals(createdCast.getReferencedObjectID(), receivedCast.getReferencedObjectID(), "mismatched ReferencedObjectID"); + assertEquals(createdCast.getUpdateNumber(), receivedCast.getUpdateNumber(), "mismatched UpdateNumber"); + assertEquals(createdCast.getForceID(), receivedCast.getForceID(), "mismatched ForceID"); + assertEquals(createdCast.getRequesterID(), receivedCast.getRequesterID(), "mismatched RequesterID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getObjectType(), receivedCast.getObjectType(), "mismatched ObjectType"); + assertEquals(createdCast.getLinearSegmentParameters(), receivedCast.getLinearSegmentParameters(), "mismatched LinearSegmentParameters"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new LinearObjectStatePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/LiveEntityDetonationPduTest.java b/test/edu/nps/moves/dis7/test/LiveEntityDetonationPduTest.java new file mode 100644 index 0000000000..35e0617742 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/LiveEntityDetonationPduTest.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EventIdentifier; +import edu.nps.moves.dis7.pdus.LEDetonationPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Live Entity Detonation PDU fields and values. + */ +@DisplayName("LiveEntityDetonationPduTest") +public class LiveEntityDetonationPduTest extends PduTest +{ + /** default constructor */ + public LiveEntityDetonationPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** LiveEntityDetonationPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** LiveEntityDetonationPduTest testMultiplePdus()"); + + LEDetonationPdu leDetPdu = pduFactory.makeLEDetonationPdu(); + + leDetPdu.setFiringLiveEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + leDetPdu.setTargetLiveEntityId(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + leDetPdu.setMunitionLiveEntityId(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + leDetPdu.setEventId(new EventIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setEventNumber(200)); + leDetPdu.setDetonationResult((byte) 1); + testOnePdu(leDetPdu); + + leDetPdu.setDetonationResult((byte) 3); + leDetPdu.setEventId(new EventIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setEventNumber(201)); + testOnePdu(leDetPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + LEDetonationPdu createdCast = (LEDetonationPdu) createdPdu; + LEDetonationPdu receivedCast = (LEDetonationPdu) receivedPdus.get(0); + + assertEquals(createdCast.getFiringLiveEntityId(), receivedCast.getFiringLiveEntityId(), "mismatched FiringLiveEntityId"); + assertEquals(createdCast.getTargetLiveEntityId(), receivedCast.getTargetLiveEntityId(), "mismatched TargetLiveEntityId"); + assertEquals(createdCast.getMunitionLiveEntityId(), receivedCast.getMunitionLiveEntityId(), "mismatched MunitionLiveEntityId"); + assertEquals(createdCast.getEventId(), receivedCast.getEventId(), "mismatched EventId"); + assertEquals(createdCast.getWorldLocation(), receivedCast.getWorldLocation(), "mismatched WorldLocation"); + assertEquals(createdCast.getVelocity(), receivedCast.getVelocity(), "mismatched Velocity"); + assertEquals(createdCast.getMunitionOrientation(), receivedCast.getMunitionOrientation(), "mismatched MunitionOrientation"); + assertEquals(createdCast.getMunitionDescriptor(), receivedCast.getMunitionDescriptor(), "mismatched MunitionDescriptor"); + assertEquals(createdCast.getEntityLocation(), receivedCast.getEntityLocation(), "mismatched EntityLocation"); + assertEquals(createdCast.getDetonationResult(), receivedCast.getDetonationResult(), "mismatched DetonationResult"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new LiveEntityDetonationPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/LiveEntityFirePduTest.java b/test/edu/nps/moves/dis7/test/LiveEntityFirePduTest.java new file mode 100644 index 0000000000..b09e5d0a5c --- /dev/null +++ b/test/edu/nps/moves/dis7/test/LiveEntityFirePduTest.java @@ -0,0 +1,116 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EventIdentifier; +import edu.nps.moves.dis7.pdus.LEFirePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Live Entity Fire PDU fields and values. + */ +@DisplayName("LiveEntityFirePduTest") +public class LiveEntityFirePduTest extends PduTest +{ + /** default constructor */ + public LiveEntityFirePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** LiveEntityFirePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** LiveEntityFirePduTest testMultiplePdus()"); + + LEFirePdu leFirePdu = pduFactory.makeLEFirePdu(); + + leFirePdu.setFiringLiveEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + leFirePdu.setTargetLiveEntityId(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + leFirePdu.setMunitionLiveEntityId(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + leFirePdu.setEventId(new EventIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setEventNumber(100)); + leFirePdu.setRange((short) 5000); + testOnePdu(leFirePdu); + + leFirePdu.setRange((short) 10000); + leFirePdu.setEventId(new EventIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setEventNumber(101)); + testOnePdu(leFirePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + LEFirePdu createdCast = (LEFirePdu) createdPdu; + LEFirePdu receivedCast = (LEFirePdu) receivedPdus.get(0); + + assertEquals(createdCast.getFiringLiveEntityId(), receivedCast.getFiringLiveEntityId(), "mismatched FiringLiveEntityId"); + assertEquals(createdCast.getTargetLiveEntityId(), receivedCast.getTargetLiveEntityId(), "mismatched TargetLiveEntityId"); + assertEquals(createdCast.getMunitionLiveEntityId(), receivedCast.getMunitionLiveEntityId(), "mismatched MunitionLiveEntityId"); + assertEquals(createdCast.getEventId(), receivedCast.getEventId(), "mismatched EventId"); + assertEquals(createdCast.getLocation(), receivedCast.getLocation(), "mismatched Location"); + assertEquals(createdCast.getMunitionDescriptor(), receivedCast.getMunitionDescriptor(), "mismatched MunitionDescriptor"); + assertEquals(createdCast.getVelocity(), receivedCast.getVelocity(), "mismatched Velocity"); + assertEquals(createdCast.getRange(), receivedCast.getRange(), "mismatched Range"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new LiveEntityFirePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/Matrix3fTest.java b/test/edu/nps/moves/dis7/test/Matrix3fTest.java new file mode 100644 index 0000000000..593901c90e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Matrix3fTest.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.legacy.math.Matrix3f; +import edu.nps.moves.legacy.math.Vec3f; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Matrix3f legacy math class. + * Validates construction, identity, Euler angles, and vector transforms. + */ +@DisplayName("Matrix3fTest") +public class Matrix3fTest +{ + private static final float TOLERANCE = 1.0e-4f; + private static boolean verbose = true; + + /** default constructor */ + public Matrix3fTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Matrix3fTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Matrix3fTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Matrix3fTest testDefaultConstructor()"); + + Matrix3f m = new Matrix3f(); + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + assertEquals(0.0f, m.getMatValue(r, c), TOLERANCE, "mismatched null matrix [" + r + "][" + c + "]"); + } + + @Test + public void testIdentity() + { + if (verbose) + System.out.println("*** Matrix3fTest testIdentity()"); + + Matrix3f m = new Matrix3f(); + m.makeIdent(); + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + { + float expected = (r == c) ? 1.0f : 0.0f; + assertEquals(expected, m.getMatValue(r, c), TOLERANCE, "mismatched identity [" + r + "][" + c + "]"); + } + } + + @Test + public void testCopyConstructor() + { + if (verbose) + System.out.println("*** Matrix3fTest testCopyConstructor()"); + + Matrix3f original = new Matrix3f(); + original.makeIdent(); + original.setMatValue(0, 1, 5.0f); + Matrix3f copy = new Matrix3f(original); + assertEquals(5.0f, copy.getMatValue(0, 1), TOLERANCE, "mismatched copy [0][1]"); + assertEquals(1.0f, copy.getMatValue(0, 0), TOLERANCE, "mismatched copy [0][0]"); + } + + @Test + public void testIdentityXformVec3f() + { + if (verbose) + System.out.println("*** Matrix3fTest testIdentityXformVec3f()"); + + Matrix3f identity = new Matrix3f(); + identity.makeIdent(); + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + identity.xform(v); + assertEquals(1.0f, v.get(0), TOLERANCE, "identity xform should not change v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "identity xform should not change v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "identity xform should not change v[2]"); + } + + @Test + public void testIdentityXformArray() + { + if (verbose) + System.out.println("*** Matrix3fTest testIdentityXformArray()"); + + Matrix3f identity = new Matrix3f(); + identity.makeIdent(); + float[] v = {1.0f, 2.0f, 3.0f}; + identity.xform(v); + assertEquals(1.0f, v[0], TOLERANCE, "identity xform should not change v[0]"); + assertEquals(2.0f, v[1], TOLERANCE, "identity xform should not change v[1]"); + assertEquals(3.0f, v[2], TOLERANCE, "identity xform should not change v[2]"); + } + + @Test + public void testSetGetEulersRoundTrip() + { + if (verbose) + System.out.println("*** Matrix3fTest testSetGetEulersRoundTrip()"); + + float heading = 0.5f; // radians + float pitch = 0.3f; + float roll = 0.1f; + + Matrix3f m = new Matrix3f(heading, pitch, roll); + float[] hpr = new float[3]; + m.getEulers(hpr); + + assertEquals(heading, hpr[0], TOLERANCE, "mismatched heading after Euler round-trip"); + assertEquals(pitch, hpr[1], TOLERANCE, "mismatched pitch after Euler round-trip"); + assertEquals(roll, hpr[2], TOLERANCE, "mismatched roll after Euler round-trip"); + } + + @Test + public void testSetEulersZero() + { + if (verbose) + System.out.println("*** Matrix3fTest testSetEulersZero()"); + + Matrix3f m = new Matrix3f(0.0f, 0.0f, 0.0f); + // with zero Eulers, matrix should be identity + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + { + float expected = (r == c) ? 1.0f : 0.0f; + assertEquals(expected, m.getMatValue(r, c), TOLERANCE, "zero Euler should give identity [" + r + "][" + c + "]"); + } + } + + @Test + public void testArrayConstructor() + { + if (verbose) + System.out.println("*** Matrix3fTest testArrayConstructor()"); + + float[][] mat = { + {1.0f, 2.0f, 3.0f}, + {4.0f, 5.0f, 6.0f}, + {7.0f, 8.0f, 9.0f} + }; + Matrix3f m = new Matrix3f(mat); + assertEquals(1.0f, m.getMatValue(0, 0), TOLERANCE, "mismatched [0][0]"); + assertEquals(5.0f, m.getMatValue(1, 1), TOLERANCE, "mismatched [1][1]"); + assertEquals(9.0f, m.getMatValue(2, 2), TOLERANCE, "mismatched [2][2]"); + assertEquals(6.0f, m.getMatValue(1, 2), TOLERANCE, "mismatched [1][2]"); + } + + @Test + public void testSetMatValue() + { + if (verbose) + System.out.println("*** Matrix3fTest testSetMatValue()"); + + Matrix3f m = new Matrix3f(); + m.setMatValue(1, 2, 42.0f); + assertEquals(42.0f, m.getMatValue(1, 2), TOLERANCE, "mismatched setMatValue"); + assertEquals(0.0f, m.getMatValue(0, 0), TOLERANCE, "other values should remain zero"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("Matrix3fTest start"); + Matrix3fTest test = new Matrix3fTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testIdentity(); + test.testCopyConstructor(); + test.testIdentityXformVec3f(); + test.testIdentityXformArray(); + test.testSetGetEulersRoundTrip(); + test.testSetEulersZero(); + test.testArrayConstructor(); + test.testSetMatValue(); + tearDownClass(); + System.out.println("Matrix3fTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/Matrix4fTest.java b/test/edu/nps/moves/dis7/test/Matrix4fTest.java new file mode 100644 index 0000000000..c02a2db382 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Matrix4fTest.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.legacy.math.Matrix4f; +import edu.nps.moves.legacy.math.Vec4f; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Matrix4f legacy math class. + * Validates construction, identity, Euler angles, and vector transforms. + */ +@DisplayName("Matrix4fTest") +public class Matrix4fTest +{ + private static final float TOLERANCE = 1.0e-4f; + private static boolean verbose = true; + + /** default constructor */ + public Matrix4fTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Matrix4fTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Matrix4fTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Matrix4fTest testDefaultConstructor()"); + + Matrix4f m = new Matrix4f(); + for (int r = 0; r < 4; r++) + for (int c = 0; c < 4; c++) + assertEquals(0.0f, m.getMatValue(r, c), TOLERANCE, "mismatched null matrix [" + r + "][" + c + "]"); + } + + @Test + public void testIdentity() + { + if (verbose) + System.out.println("*** Matrix4fTest testIdentity()"); + + Matrix4f m = new Matrix4f(); + m.makeIdent(); + for (int r = 0; r < 4; r++) + for (int c = 0; c < 4; c++) + { + float expected = (r == c) ? 1.0f : 0.0f; + assertEquals(expected, m.getMatValue(r, c), TOLERANCE, "mismatched identity [" + r + "][" + c + "]"); + } + } + + @Test + public void testCopyConstructor() + { + if (verbose) + System.out.println("*** Matrix4fTest testCopyConstructor()"); + + Matrix4f original = new Matrix4f(); + original.makeIdent(); + original.setMatValue(0, 3, 7.0f); + Matrix4f copy = new Matrix4f(original); + assertEquals(7.0f, copy.getMatValue(0, 3), TOLERANCE, "mismatched copy [0][3]"); + assertEquals(1.0f, copy.getMatValue(0, 0), TOLERANCE, "mismatched copy [0][0]"); + } + + @Test + public void testIdentityXformVec4f() + { + if (verbose) + System.out.println("*** Matrix4fTest testIdentityXformVec4f()"); + + Matrix4f identity = new Matrix4f(); + identity.makeIdent(); + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + identity.xform(v); + assertEquals(1.0f, v.get(0), TOLERANCE, "identity xform should not change v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "identity xform should not change v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "identity xform should not change v[2]"); + assertEquals(4.0f, v.get(3), TOLERANCE, "identity xform should not change v[3]"); + } + + @Test + public void testSetEulersZero() + { + if (verbose) + System.out.println("*** Matrix4fTest testSetEulersZero()"); + + Matrix4f m = new Matrix4f(0.0f, 0.0f, 0.0f); + // zero Eulers should give identity + for (int r = 0; r < 4; r++) + for (int c = 0; c < 4; c++) + { + float expected = (r == c) ? 1.0f : 0.0f; + assertEquals(expected, m.getMatValue(r, c), TOLERANCE, "zero Euler should give identity [" + r + "][" + c + "]"); + } + } + + @Test + public void testSetEulersBottomRow() + { + if (verbose) + System.out.println("*** Matrix4fTest testSetEulersBottomRow()"); + + Matrix4f m = new Matrix4f(0.5f, 0.3f, 0.1f); + // bottom row and right column should be [0,0,0,1] pattern for rotation matrix + assertEquals(0.0f, m.getMatValue(3, 0), TOLERANCE, "mismatched [3][0]"); + assertEquals(0.0f, m.getMatValue(3, 1), TOLERANCE, "mismatched [3][1]"); + assertEquals(0.0f, m.getMatValue(3, 2), TOLERANCE, "mismatched [3][2]"); + assertEquals(1.0f, m.getMatValue(3, 3), TOLERANCE, "mismatched [3][3]"); + assertEquals(0.0f, m.getMatValue(0, 3), TOLERANCE, "mismatched [0][3]"); + assertEquals(0.0f, m.getMatValue(1, 3), TOLERANCE, "mismatched [1][3]"); + assertEquals(0.0f, m.getMatValue(2, 3), TOLERANCE, "mismatched [2][3]"); + } + + @Test + public void testArrayConstructor() + { + if (verbose) + System.out.println("*** Matrix4fTest testArrayConstructor()"); + + float[][] mat = { + {1.0f, 2.0f, 3.0f, 4.0f}, + {5.0f, 6.0f, 7.0f, 8.0f}, + {9.0f, 10.0f, 11.0f, 12.0f}, + {13.0f, 14.0f, 15.0f, 16.0f} + }; + Matrix4f m = new Matrix4f(mat); + assertEquals(1.0f, m.getMatValue(0, 0), TOLERANCE, "mismatched [0][0]"); + assertEquals(6.0f, m.getMatValue(1, 1), TOLERANCE, "mismatched [1][1]"); + assertEquals(11.0f, m.getMatValue(2, 2), TOLERANCE, "mismatched [2][2]"); + assertEquals(16.0f, m.getMatValue(3, 3), TOLERANCE, "mismatched [3][3]"); + } + + @Test + public void testSetMatValue() + { + if (verbose) + System.out.println("*** Matrix4fTest testSetMatValue()"); + + Matrix4f m = new Matrix4f(); + m.setMatValue(2, 3, 99.0f); + assertEquals(99.0f, m.getMatValue(2, 3), TOLERANCE, "mismatched setMatValue"); + assertEquals(0.0f, m.getMatValue(0, 0), TOLERANCE, "other values should remain zero"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("Matrix4fTest start"); + Matrix4fTest test = new Matrix4fTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testIdentity(); + test.testCopyConstructor(); + test.testIdentityXformVec4f(); + test.testSetEulersZero(); + test.testSetEulersBottomRow(); + test.testArrayConstructor(); + test.testSetMatValue(); + tearDownClass(); + System.out.println("Matrix4fTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/MinefieldDataPduTest.java b/test/edu/nps/moves/dis7/test/MinefieldDataPduTest.java new file mode 100644 index 0000000000..3fcbb38872 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/MinefieldDataPduTest.java @@ -0,0 +1,125 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.MinefieldDataPdu; +import edu.nps.moves.dis7.pdus.MinefieldIdentifier; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Minefield Data PDU fields and values. + */ +@DisplayName("MinefieldDataPduTest") +public class MinefieldDataPduTest extends PduTest +{ + /** default constructor */ + public MinefieldDataPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** MinefieldDataPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** MinefieldDataPduTest testMultiplePdus()"); + + MinefieldDataPdu mdPdu = pduFactory.makeMinefieldDataPdu(); + + mdPdu.setMinefieldID(new MinefieldIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setMinefieldNumber(100)); + mdPdu.setRequestingEntityID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + mdPdu.setMinefieldSequenceNumbeer((short) 1); + mdPdu.setRequestID((byte) 1); + mdPdu.setPduSequenceNumber((byte) 1); + mdPdu.setNumberOfPdus((byte) 1); + mdPdu.setMineType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + testOnePdu(mdPdu); + + mdPdu.setMinefieldSequenceNumbeer((short) 2); + mdPdu.setRequestID((byte) 2); + testOnePdu(mdPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + MinefieldDataPdu createdCast = (MinefieldDataPdu) createdPdu; + MinefieldDataPdu receivedCast = (MinefieldDataPdu) receivedPdus.get(0); + + assertEquals(createdCast.getMinefieldID(), receivedCast.getMinefieldID(), "mismatched MinefieldID"); + assertEquals(createdCast.getRequestingEntityID(), receivedCast.getRequestingEntityID(), "mismatched RequestingEntityID"); + assertEquals(createdCast.getMinefieldSequenceNumbeer(), receivedCast.getMinefieldSequenceNumbeer(), "mismatched MinefieldSequenceNumbeer"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getPduSequenceNumber(), receivedCast.getPduSequenceNumber(), "mismatched PduSequenceNumber"); + assertEquals(createdCast.getNumberOfPdus(), receivedCast.getNumberOfPdus(), "mismatched NumberOfPdus"); + assertEquals(createdCast.getDataFilter(), receivedCast.getDataFilter(), "mismatched DataFilter"); + assertEquals(createdCast.getMineType(), receivedCast.getMineType(), "mismatched MineType"); + assertEquals(createdCast.getSensorTypes(), receivedCast.getSensorTypes(), "mismatched SensorTypes"); + assertEquals(createdCast.getMineLocation(), receivedCast.getMineLocation(), "mismatched MineLocation"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new MinefieldDataPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/MinefieldQueryPduTest.java b/test/edu/nps/moves/dis7/test/MinefieldQueryPduTest.java new file mode 100644 index 0000000000..e2c4d5dd4b --- /dev/null +++ b/test/edu/nps/moves/dis7/test/MinefieldQueryPduTest.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.MinefieldIdentifier; +import edu.nps.moves.dis7.pdus.MinefieldQueryPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Minefield Query PDU fields and values. + */ +@DisplayName("MinefieldQueryPduTest") +public class MinefieldQueryPduTest extends PduTest +{ + /** default constructor */ + public MinefieldQueryPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** MinefieldQueryPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** MinefieldQueryPduTest testMultiplePdus()"); + + MinefieldQueryPdu mqPdu = pduFactory.makeMinefieldQueryPdu(); + + mqPdu.setMinefieldID(new MinefieldIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setMinefieldNumber(100)); + mqPdu.setRequestingEntityID(new EntityID().setSiteID(3).setApplicationID(4).setEntityID(5)); + mqPdu.setRequestID((byte) 1); + mqPdu.setRequestedMineType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + testOnePdu(mqPdu); + + mqPdu.setRequestID((byte) 2); + testOnePdu(mqPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + MinefieldQueryPdu createdCast = (MinefieldQueryPdu) createdPdu; + MinefieldQueryPdu receivedCast = (MinefieldQueryPdu) receivedPdus.get(0); + + assertEquals(createdCast.getMinefieldID(), receivedCast.getMinefieldID(), "mismatched MinefieldID"); + assertEquals(createdCast.getRequestingEntityID(), receivedCast.getRequestingEntityID(), "mismatched RequestingEntityID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getDataFilter(), receivedCast.getDataFilter(), "mismatched DataFilter"); + assertEquals(createdCast.getRequestedMineType(), receivedCast.getRequestedMineType(), "mismatched RequestedMineType"); + assertEquals(createdCast.getRequestedPerimeterPoints(), receivedCast.getRequestedPerimeterPoints(), "mismatched RequestedPerimeterPoints"); + assertEquals(createdCast.getSensorTypes(), receivedCast.getSensorTypes(), "mismatched SensorTypes"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new MinefieldQueryPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/MinefieldResponseNACKPduTest.java b/test/edu/nps/moves/dis7/test/MinefieldResponseNACKPduTest.java new file mode 100644 index 0000000000..b06425493f --- /dev/null +++ b/test/edu/nps/moves/dis7/test/MinefieldResponseNACKPduTest.java @@ -0,0 +1,109 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.MinefieldIdentifier; +import edu.nps.moves.dis7.pdus.MinefieldResponseNACKPdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Minefield Response NACK PDU fields and values. + */ +@DisplayName("MinefieldResponseNACKPduTest") +public class MinefieldResponseNACKPduTest extends PduTest +{ + /** default constructor */ + public MinefieldResponseNACKPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** MinefieldResponseNACKPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** MinefieldResponseNACKPduTest testMultiplePdus()"); + + MinefieldResponseNACKPdu mrnPdu = pduFactory.makeMinefieldResponseNackPdu(); + + mrnPdu.setMinefieldID(new MinefieldIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setMinefieldNumber(100)); + mrnPdu.setRequestingEntityID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + mrnPdu.setRequestID((byte) 1); + testOnePdu(mrnPdu); + + mrnPdu.setRequestID((byte) 2); + testOnePdu(mrnPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + MinefieldResponseNACKPdu createdCast = (MinefieldResponseNACKPdu) createdPdu; + MinefieldResponseNACKPdu receivedCast = (MinefieldResponseNACKPdu) receivedPdus.get(0); + + assertEquals(createdCast.getMinefieldID(), receivedCast.getMinefieldID(), "mismatched MinefieldID"); + assertEquals(createdCast.getRequestingEntityID(), receivedCast.getRequestingEntityID(), "mismatched RequestingEntityID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertArrayEquals(createdCast.getMissingPduSequenceNumbers(), receivedCast.getMissingPduSequenceNumbers(), "mismatched MissingPduSequenceNumbers"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new MinefieldResponseNACKPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/MinefieldStatePduTest.java b/test/edu/nps/moves/dis7/test/MinefieldStatePduTest.java new file mode 100644 index 0000000000..51f4b4359c --- /dev/null +++ b/test/edu/nps/moves/dis7/test/MinefieldStatePduTest.java @@ -0,0 +1,126 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.pdus.EulerAngles; +import edu.nps.moves.dis7.pdus.MinefieldIdentifier; +import edu.nps.moves.dis7.pdus.MinefieldStatePdu; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.Vector3Double; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.pdus.Domain; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.Country; + +/** + * Unit tests for satisfactory handling of Minefield State PDU fields and values. + */ +@DisplayName("MinefieldStatePduTest") +public class MinefieldStatePduTest extends PduTest +{ + /** default constructor */ + public MinefieldStatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** MinefieldStatePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** MinefieldStatePduTest testMultiplePdus()"); + + MinefieldStatePdu msPdu = pduFactory.makeMinefieldStatePdu(); + + msPdu.setMinefieldID(new MinefieldIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2)).setMinefieldNumber(100)); + msPdu.setMinefieldSequence((short) 1); + msPdu.setForceID(ForceID.FRIENDLY); + msPdu.setMinefieldType(new EntityType().setEntityKind(EntityKind.PLATFORM).setDomain(Domain.inst(PlatformDomain.LAND)).setCountry(Country.UNITED_STATES_OF_AMERICA_USA)); + msPdu.setMinefieldLocation(new Vector3Double().setX(1000.0).setY(2000.0).setZ(0.0)); + msPdu.setMinefieldOrientation(new EulerAngles().setPhi(0.0f).setTheta(0.0f).setPsi(1.57f)); + testOnePdu(msPdu); + + msPdu.setMinefieldSequence((short) 2); + msPdu.setMinefieldLocation(new Vector3Double().setX(3000.0).setY(4000.0).setZ(0.0)); + testOnePdu(msPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + MinefieldStatePdu createdCast = (MinefieldStatePdu) createdPdu; + MinefieldStatePdu receivedCast = (MinefieldStatePdu) receivedPdus.get(0); + + assertEquals(createdCast.getMinefieldID(), receivedCast.getMinefieldID(), "mismatched MinefieldID"); + assertEquals(createdCast.getMinefieldSequence(), receivedCast.getMinefieldSequence(), "mismatched MinefieldSequence"); + assertEquals(createdCast.getForceID(), receivedCast.getForceID(), "mismatched ForceID"); + assertEquals(createdCast.getMinefieldType(), receivedCast.getMinefieldType(), "mismatched MinefieldType"); + assertEquals(createdCast.getMinefieldLocation(), receivedCast.getMinefieldLocation(), "mismatched MinefieldLocation"); + assertEquals(createdCast.getMinefieldOrientation(), receivedCast.getMinefieldOrientation(), "mismatched MinefieldOrientation"); + assertEquals(createdCast.getAppearance(), receivedCast.getAppearance(), "mismatched Appearance"); + assertEquals(createdCast.getProtocolMode(), receivedCast.getProtocolMode(), "mismatched ProtocolMode"); + assertEquals(createdCast.getPerimeterPoints(), receivedCast.getPerimeterPoints(), "mismatched PerimeterPoints"); + assertEquals(createdCast.getMineType(), receivedCast.getMineType(), "mismatched MineType"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new MinefieldStatePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ModulationTypeTest.java b/test/edu/nps/moves/dis7/test/ModulationTypeTest.java new file mode 100644 index 0000000000..194c06a48e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ModulationTypeTest.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ModulationType; +import edu.nps.moves.dis7.enumerations.TransmitterMajorModulation; +import edu.nps.moves.dis7.enumerations.TransmitterModulationTypeSystem; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for ModulationType data structure. + * Validates construction, field access, and marshal/unmarshal round-trip. + */ +@DisplayName("ModulationTypeTest") +public class ModulationTypeTest +{ + private static boolean verbose = true; + + /** default constructor */ + public ModulationTypeTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** ModulationTypeTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** ModulationTypeTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** ModulationTypeTest testDefaultConstructor()"); + + ModulationType mt = new ModulationType(); + assertEquals(0, mt.getSpreadSpectrum(), "mismatched default spreadSpectrum"); + assertEquals(0, mt.getDetail(), "mismatched default detail"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** ModulationTypeTest testSettersAndGetters()"); + + ModulationType mt = new ModulationType(); + mt.setSpreadSpectrum(1); + mt.setMajorModulation(TransmitterMajorModulation.AMPLITUDE_2); + mt.setDetail(3); + mt.setRadioSystem(TransmitterModulationTypeSystem.GENERIC_RADIO_OR_SIMPLE_INTERCOM); + + assertEquals(1, mt.getSpreadSpectrum(), "mismatched spreadSpectrum"); + assertEquals(TransmitterMajorModulation.AMPLITUDE_2, mt.getMajorModulation(), "mismatched majorModulation"); + assertEquals(3, mt.getDetail(), "mismatched detail"); + assertEquals(TransmitterModulationTypeSystem.GENERIC_RADIO_OR_SIMPLE_INTERCOM, mt.getRadioSystem(), "mismatched radioSystem"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** ModulationTypeTest testMarshalUnmarshalDataStream()"); + + ModulationType original = new ModulationType(); + original.setSpreadSpectrum(2); + original.setMajorModulation(TransmitterMajorModulation.AMPLITUDE_2); + original.setDetail(5); + original.setRadioSystem(TransmitterModulationTypeSystem.GENERIC_RADIO_OR_SIMPLE_INTERCOM); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + ModulationType restored = new ModulationType(); + restored.unmarshal(dis); + + assertEquals(original.getSpreadSpectrum(), restored.getSpreadSpectrum(), "mismatched spreadSpectrum after unmarshal"); + assertEquals(original.getMajorModulation(), restored.getMajorModulation(), "mismatched majorModulation after unmarshal"); + assertEquals(original.getDetail(), restored.getDetail(), "mismatched detail after unmarshal"); + assertEquals(original.getRadioSystem(), restored.getRadioSystem(), "mismatched radioSystem after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** ModulationTypeTest testMarshalUnmarshalByteBuffer()"); + + ModulationType original = new ModulationType(); + original.setSpreadSpectrum(0); + original.setMajorModulation(TransmitterMajorModulation.AMPLITUDE_2); + original.setDetail(1); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + ModulationType restored = new ModulationType(); + restored.unmarshal(buffer); + + assertEquals(original.getSpreadSpectrum(), restored.getSpreadSpectrum(), "mismatched spreadSpectrum after ByteBuffer unmarshal"); + assertEquals(original.getMajorModulation(), restored.getMajorModulation(), "mismatched majorModulation after ByteBuffer unmarshal"); + assertEquals(original.getDetail(), restored.getDetail(), "mismatched detail after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** ModulationTypeTest testEquality()"); + + ModulationType a = new ModulationType(); + a.setSpreadSpectrum(1); + a.setDetail(2); + ModulationType b = new ModulationType(); + b.setSpreadSpectrum(1); + b.setDetail(2); + ModulationType c = new ModulationType(); + c.setSpreadSpectrum(1); + c.setDetail(3); + + assertTrue(a.equals(b), "equal ModulationTypes should be equal"); + assertFalse(a.equals(c), "different ModulationTypes should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("ModulationTypeTest start"); + ModulationTypeTest test = new ModulationTypeTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("ModulationTypeTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/MunitionDescriptorTest.java b/test/edu/nps/moves/dis7/test/MunitionDescriptorTest.java new file mode 100644 index 0000000000..a71055cb21 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/MunitionDescriptorTest.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.MunitionDescriptor; +import edu.nps.moves.dis7.pdus.EntityType; +import edu.nps.moves.dis7.enumerations.EntityKind; +import edu.nps.moves.dis7.enumerations.MunitionDescriptorWarhead; +import edu.nps.moves.dis7.enumerations.MunitionDescriptorFuse; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for MunitionDescriptor data structure. + * Validates construction, field access, and marshal/unmarshal round-trip. + */ +@DisplayName("MunitionDescriptorTest") +public class MunitionDescriptorTest +{ + private static boolean verbose = true; + + /** default constructor */ + public MunitionDescriptorTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** MunitionDescriptorTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** MunitionDescriptorTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** MunitionDescriptorTest testDefaultConstructor()"); + + MunitionDescriptor md = new MunitionDescriptor(); + assertNotNull(md.getMunitionType(), "munitionType should not be null"); + assertEquals(0, md.getQuantity(), "mismatched default quantity"); + assertEquals(0, md.getRate(), "mismatched default rate"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** MunitionDescriptorTest testSettersAndGetters()"); + + MunitionDescriptor md = new MunitionDescriptor(); + md.getMunitionType().setEntityKind(EntityKind.MUNITION); + md.getMunitionType().setCategory(2); + md.setWarhead(MunitionDescriptorWarhead.HIGH_EXPLOSIVE_HE); + md.setFuse(MunitionDescriptorFuse.CONTACT_INSTANT_IMPACT); + md.setQuantity(10); + md.setRate(5); + + assertEquals(EntityKind.MUNITION, md.getMunitionType().getEntityKind(), "mismatched entityKind"); + assertEquals(2, md.getMunitionType().getCategory(), "mismatched category"); + assertEquals(MunitionDescriptorWarhead.HIGH_EXPLOSIVE_HE, md.getWarhead(), "mismatched warhead"); + assertEquals(MunitionDescriptorFuse.CONTACT_INSTANT_IMPACT, md.getFuse(), "mismatched fuse"); + assertEquals(10, md.getQuantity(), "mismatched quantity"); + assertEquals(5, md.getRate(), "mismatched rate"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** MunitionDescriptorTest testMarshalUnmarshalDataStream()"); + + MunitionDescriptor original = new MunitionDescriptor(); + original.getMunitionType().setEntityKind(EntityKind.MUNITION); + original.getMunitionType().setCategory(1); + original.getMunitionType().setSubCategory(2); + original.setWarhead(MunitionDescriptorWarhead.HIGH_EXPLOSIVE_HE); + original.setFuse(MunitionDescriptorFuse.CONTACT_INSTANT_IMPACT); + original.setQuantity(50); + original.setRate(10); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + MunitionDescriptor restored = new MunitionDescriptor(); + restored.unmarshal(dis); + + assertEquals(original.getMunitionType().getEntityKind(), restored.getMunitionType().getEntityKind(), "mismatched entityKind after unmarshal"); + assertEquals(original.getMunitionType().getCategory(), restored.getMunitionType().getCategory(), "mismatched category after unmarshal"); + assertEquals(original.getWarhead(), restored.getWarhead(), "mismatched warhead after unmarshal"); + assertEquals(original.getFuse(), restored.getFuse(), "mismatched fuse after unmarshal"); + assertEquals(original.getQuantity(), restored.getQuantity(), "mismatched quantity after unmarshal"); + assertEquals(original.getRate(), restored.getRate(), "mismatched rate after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** MunitionDescriptorTest testMarshalUnmarshalByteBuffer()"); + + MunitionDescriptor original = new MunitionDescriptor(); + original.getMunitionType().setEntityKind(EntityKind.MUNITION); + original.setQuantity(1); + original.setRate(0); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + MunitionDescriptor restored = new MunitionDescriptor(); + restored.unmarshal(buffer); + + assertEquals(original.getMunitionType().getEntityKind(), restored.getMunitionType().getEntityKind(), "mismatched entityKind after ByteBuffer unmarshal"); + assertEquals(original.getQuantity(), restored.getQuantity(), "mismatched quantity after ByteBuffer unmarshal"); + assertEquals(original.getRate(), restored.getRate(), "mismatched rate after ByteBuffer unmarshal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("MunitionDescriptorTest start"); + MunitionDescriptorTest test = new MunitionDescriptorTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + tearDownClass(); + System.out.println("MunitionDescriptorTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/PduFactoryExtendedTest.java b/test/edu/nps/moves/dis7/test/PduFactoryExtendedTest.java new file mode 100644 index 0000000000..6d83d2f3b0 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/PduFactoryExtendedTest.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.Country; +import edu.nps.moves.dis7.enumerations.DisPduType; +import edu.nps.moves.dis7.pdus.*; +import edu.nps.moves.dis7.utilities.DisTime.TimestampStyle; +import edu.nps.moves.dis7.utilities.PduFactory; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Extended unit tests for PduFactory utility class. + * Validates factory configuration, PDU creation with custom parameters, + * timestamp assignment, header consistency, and deserialization. + * Supplements existing PduFactoryTest with deeper coverage. + */ +@DisplayName("PduFactoryExtendedTest") +public class PduFactoryExtendedTest +{ + private static boolean verbose = true; + + /** default constructor */ + public PduFactoryExtendedTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest tearDownClass()"); + } + + @Test + public void testDefaultFactory() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testDefaultFactory()"); + + PduFactory factory = new PduFactory(); + assertNotNull(factory, "factory should not be null"); + assertEquals(TimestampStyle.IEEE_ABSOLUTE, factory.getTimestampStyle(), "mismatched default timestamp style"); + } + + @Test + public void testCustomTimestampStyle() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testCustomTimestampStyle()"); + + PduFactory factory = new PduFactory(TimestampStyle.IEEE_RELATIVE); + assertEquals(TimestampStyle.IEEE_RELATIVE, factory.getTimestampStyle(), "mismatched custom timestamp style"); + + factory.setTimestampStyle(TimestampStyle.UNIX); + assertEquals(TimestampStyle.UNIX, factory.getTimestampStyle(), "mismatched timestamp style after set"); + } + + @Test + public void testFullConstructor() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testFullConstructor()"); + + PduFactory factory = new PduFactory(Country.UNITED_STATES_OF_AMERICA_USA, + (byte) 5, (short) 10, (short) 20, TimestampStyle.IEEE_ABSOLUTE); + assertNotNull(factory, "factory should not be null"); + + EntityStatePdu espdu = factory.makeEntityStatePdu(); + assertNotNull(espdu, "ESPDU should not be null"); + assertEquals(5, espdu.getExerciseID(), "mismatched exerciseID"); + } + + @Test + public void testMakeEntityStatePdu() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeEntityStatePdu()"); + + PduFactory factory = new PduFactory(); + EntityStatePdu espdu = factory.makeEntityStatePdu(); + assertNotNull(espdu, "ESPDU should not be null"); + assertEquals(DisPduType.ENTITY_STATE, espdu.getPduType(), "mismatched PDU type"); + assertTrue(espdu.getTimestamp() != 0, "timestamp should be set"); + } + + @Test + public void testMakeFirePdu() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeFirePdu()"); + + PduFactory factory = new PduFactory(); + FirePdu firePdu = factory.makeFirePdu(); + assertNotNull(firePdu, "FirePdu should not be null"); + assertEquals(DisPduType.FIRE, firePdu.getPduType(), "mismatched PDU type"); + } + + @Test + public void testMakeDetonationPdu() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeDetonationPdu()"); + + PduFactory factory = new PduFactory(); + DetonationPdu detPdu = factory.makeDetonationPdu(); + assertNotNull(detPdu, "DetonationPdu should not be null"); + assertEquals(DisPduType.DETONATION, detPdu.getPduType(), "mismatched PDU type"); + } + + @Test + public void testMakeCommentPduWithStrings() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeCommentPduWithStrings()"); + + PduFactory factory = new PduFactory(); + CommentPdu commentPdu = factory.makeCommentPdu("test message one", "test message two"); + assertNotNull(commentPdu, "CommentPdu should not be null"); + assertEquals(DisPduType.COMMENT, commentPdu.getPduType(), "mismatched PDU type"); + assertEquals(2, commentPdu.getVariableDatums().size(), "mismatched variable datum count"); + } + + @Test + public void testHeaderConsistencyAcrossPduTypes() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testHeaderConsistencyAcrossPduTypes()"); + + PduFactory factory = new PduFactory(Country.UNITED_STATES_OF_AMERICA_USA, + (byte) 7, (short) 100, (short) 200, TimestampStyle.IEEE_ABSOLUTE); + + EntityStatePdu espdu = factory.makeEntityStatePdu(); + FirePdu firePdu = factory.makeFirePdu(); + DetonationPdu detPdu = factory.makeDetonationPdu(); + + // exercise ID should be consistent across all PDUs from same factory + assertEquals(espdu.getExerciseID(), firePdu.getExerciseID(), "mismatched exerciseID between ESPDU and FirePdu"); + assertEquals(espdu.getExerciseID(), detPdu.getExerciseID(), "mismatched exerciseID between ESPDU and DetonationPdu"); + assertEquals(7, espdu.getExerciseID(), "mismatched exerciseID value"); + } + + @Test + public void testMarshalUnmarshalRoundTrip() throws Exception + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMarshalUnmarshalRoundTrip()"); + + PduFactory factory = new PduFactory(); + EntityStatePdu original = factory.makeEntityStatePdu(); + original.getEntityID().setSiteID(10).setApplicationID(20).setEntityID(30); + + ByteBuffer buffer = original.marshal(); + assertNotNull(buffer, "marshal result should not be null"); + assertTrue(buffer.limit() > 0, "marshalled buffer should not be empty"); + + Pdu restored = factory.createPdu(buffer); + assertNotNull(restored, "deserialized PDU should not be null"); + assertEquals(DisPduType.ENTITY_STATE, restored.getPduType(), "mismatched PDU type after round-trip"); + } + + @Test + public void testCreatePduByType() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testCreatePduByType()"); + + PduFactory factory = new PduFactory(); + Pdu firePdu = factory.createPdu(DisPduType.FIRE); + assertNotNull(firePdu, "PDU created by type should not be null"); + assertEquals(DisPduType.FIRE, firePdu.getPduType(), "mismatched PDU type"); + + Pdu espdu = factory.createPdu(DisPduType.ENTITY_STATE); + assertNotNull(espdu, "PDU created by type should not be null"); + assertEquals(DisPduType.ENTITY_STATE, espdu.getPduType(), "mismatched PDU type"); + } + + @Test + public void testMakeCollisionPdu() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeCollisionPdu()"); + + PduFactory factory = new PduFactory(); + CollisionPdu collisionPdu = factory.makeCollisionPdu(); + assertNotNull(collisionPdu, "CollisionPdu should not be null"); + assertEquals(DisPduType.COLLISION, collisionPdu.getPduType(), "mismatched PDU type"); + } + + @Test + public void testMakeCreateEntityPdu() + { + if (verbose) + System.out.println("*** PduFactoryExtendedTest testMakeCreateEntityPdu()"); + + PduFactory factory = new PduFactory(); + CreateEntityPdu createPdu = factory.makeCreateEntityPdu(); + assertNotNull(createPdu, "CreateEntityPdu should not be null"); + assertEquals(DisPduType.CREATE_ENTITY, createPdu.getPduType(), "mismatched PDU type"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("PduFactoryExtendedTest start"); + PduFactoryExtendedTest test = new PduFactoryExtendedTest(); + setUpClass(); + test.testDefaultFactory(); + test.testCustomTimestampStyle(); + test.testFullConstructor(); + test.testMakeEntityStatePdu(); + test.testMakeFirePdu(); + test.testMakeDetonationPdu(); + test.testMakeCommentPduWithStrings(); + test.testHeaderConsistencyAcrossPduTypes(); + test.testMarshalUnmarshalRoundTrip(); + test.testCreatePduByType(); + test.testMakeCollisionPdu(); + test.testMakeCreateEntityPdu(); + tearDownClass(); + System.out.println("PduFactoryExtendedTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/PduRecorderTest.java b/test/edu/nps/moves/dis7/test/PduRecorderTest.java new file mode 100644 index 0000000000..db126c8579 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/PduRecorderTest.java @@ -0,0 +1,370 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.stream.PduRecorder; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for PduRecorder utility class. + * Tests configuration, encoding options, and parameter access + * without requiring network access. + */ +@DisplayName("PduRecorderTest") +public class PduRecorderTest +{ + private static boolean verbose = true; + + /** default constructor */ + public PduRecorderTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** PduRecorderTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** PduRecorderTest tearDownClass()"); + } + + @Test + public void testFullConstructor() + { + if (verbose) + System.out.println("*** PduRecorderTest testFullConstructor()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + assertNotNull(recorder, "PduRecorder should not be null"); + assertEquals("239.1.2.3", recorder.getAddress(), "mismatched address"); + assertEquals(3000, recorder.getPort(), "mismatched port"); + } + + @Test + public void testDefaultAddress() + { + if (verbose) + System.out.println("*** PduRecorderTest testDefaultAddress()"); + + assertEquals("239.1.2.3", PduRecorder.DEFAULT_DIS_ADDRESS, "mismatched default DIS address"); + } + + @Test + public void testDefaultPort() + { + if (verbose) + System.out.println("*** PduRecorderTest testDefaultPort()"); + + assertEquals(3000, PduRecorder.DEFAULT_DIS_PORT, "mismatched default DIS port"); + } + + @Test + public void testSetAddress() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetAddress()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setAddress("239.1.2.4"); + assertEquals("239.1.2.4", recorder.getAddress(), "mismatched address after set"); + } + + @Test + public void testSetPort() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetPort()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setPort(4000); + assertEquals(4000, recorder.getPort(), "mismatched port after set"); + } + + @Test + public void testSetDescriptor() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetDescriptor()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setDescriptor("test recorder"); + assertEquals("test recorder", recorder.getDescriptor(), "mismatched descriptor after set"); + } + + @Test + public void testDefaultEncoding() + { + if (verbose) + System.out.println("*** PduRecorderTest testDefaultEncoding()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + assertEquals(PduRecorder.ENCODING_PLAINTEXT, recorder.getEncodingPduLog(), "mismatched default encoding"); + } + + @Test + public void testSetEncodingBase64() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetEncodingBase64()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setEncodingPduLog(PduRecorder.ENCODING_BASE64); + assertEquals(PduRecorder.ENCODING_BASE64, recorder.getEncodingPduLog(), "mismatched encoding after set to BASE64"); + } + + @Test + public void testSetEncodingBinary() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetEncodingBinary()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setEncodingPduLog(PduRecorder.ENCODING_BINARY); + assertEquals(PduRecorder.ENCODING_BINARY, recorder.getEncodingPduLog(), "mismatched encoding after set to BINARY"); + } + + @Test + public void testUnsupportedEncodingIgnored() + { + if (verbose) + System.out.println("*** PduRecorderTest testUnsupportedEncodingIgnored()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + String originalEncoding = recorder.getEncodingPduLog(); + recorder.setEncodingPduLog(PduRecorder.ENCODING_XML); // TODO encoding, not yet supported + assertEquals(originalEncoding, recorder.getEncodingPduLog(), "encoding should be unchanged for unsupported type"); + } + + @Test + public void testSetLogFileName() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetLogFileName()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setLogFileName("custom_log.dislog"); + assertEquals("custom_log.dislog", recorder.getLogFileName(), "mismatched log file name after set"); + } + + @Test + public void testDefaultLogFileName() + { + if (verbose) + System.out.println("*** PduRecorderTest testDefaultLogFileName()"); + + assertEquals("PduCaptureLog.dislog", PduRecorder.DEFAULT_FILE_NAME, "mismatched default file name"); + } + + @Test + public void testSetOutputDirectory() + { + if (verbose) + System.out.println("*** PduRecorderTest testSetOutputDirectory()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setOutputDirectory("./customDir"); + assertEquals("./customDir", recorder.getOutputDirectory(), "mismatched output directory after set"); + assertNotNull(recorder.getOutputDirectoryPath(), "output directory path should not be null"); + } + + @Test + public void testVerboseSettings() + { + if (verbose) + System.out.println("*** PduRecorderTest testVerboseSettings()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setVerbose(false); + assertFalse(recorder.hasVerboseOutput(), "verbose should be false after set"); + assertFalse(recorder.hasVerboseReceipt(), "verboseReceipt should be false after setVerbose(false)"); + assertFalse(recorder.hasVerboseSending(), "verboseSending should be false after setVerbose(false)"); + + recorder.setVerbose(true); + assertTrue(recorder.hasVerboseOutput(), "verbose should be true after set"); + } + + @Test + public void testVerboseReceiptSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testVerboseReceiptSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setVerboseReceipt(false); + assertFalse(recorder.hasVerboseReceipt(), "verboseReceipt should be false after set"); + + recorder.setVerboseReceipt(true); + assertTrue(recorder.hasVerboseReceipt(), "verboseReceipt should be true after set"); + } + + @Test + public void testVerboseSendingSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testVerboseSendingSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setVerboseSending(false); + assertFalse(recorder.hasVerboseSending(), "verboseSending should be false after set"); + + recorder.setVerboseSending(true); + assertTrue(recorder.hasVerboseSending(), "verboseSending should be true after set"); + } + + @Test + public void testVerboseTimestampSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testVerboseTimestampSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + recorder.setVerboseIncludesTimestamp(true); + assertTrue(recorder.hasVerboseOutputIncludesTimestamp(), "verboseIncludesTimestamp should be true after set"); + + recorder.setVerboseIncludesTimestamp(false); + assertFalse(recorder.hasVerboseOutputIncludesTimestamp(), "verboseIncludesTimestamp should be false after set"); + } + + @Test + public void testReadableTimeStampSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testReadableTimeStampSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + assertTrue(recorder.includesReadableTimeStamp(), "readableTimeStamp should default to true"); + + recorder.setReadableTimeStamp(false); + assertFalse(recorder.includesReadableTimeStamp(), "readableTimeStamp should be false after set"); + } + + @Test + public void testZeroBasedTimeStampSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testZeroBasedTimeStampSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + assertTrue(recorder.isZeroBasedTimeStamp(), "zeroBasedTimeStamp should default to true"); + + recorder.setZeroBasedTimeStamp(false); + assertFalse(recorder.isZeroBasedTimeStamp(), "zeroBasedTimeStamp should be false after set"); + } + + @Test + public void testIncludeHeadersSetting() + { + if (verbose) + System.out.println("*** PduRecorderTest testIncludeHeadersSetting()"); + + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + // default with plaintext encoding should include headers + assertTrue(recorder.isIncludeHeaders(), "includeHeaders should default to true for plaintext encoding"); + + recorder.setIncludeHeaders(false); + assertFalse(recorder.isIncludeHeaders(), "includeHeaders should be false after set"); + } + + @Test + public void testEncodingConstants() + { + if (verbose) + System.out.println("*** PduRecorderTest testEncodingConstants()"); + + assertEquals("ENCODING_PLAINTEXT", PduRecorder.ENCODING_PLAINTEXT, "mismatched ENCODING_PLAINTEXT"); + assertEquals("ENCODING_BASE64", PduRecorder.ENCODING_BASE64, "mismatched ENCODING_BASE64"); + assertEquals("ENCODING_BINARY", PduRecorder.ENCODING_BINARY, "mismatched ENCODING_BINARY"); + assertEquals("ENCODING_XML", PduRecorder.ENCODING_XML, "mismatched ENCODING_XML"); + assertEquals("ENCODING_EXI", PduRecorder.ENCODING_EXI, "mismatched ENCODING_EXI"); + assertEquals("ENCODING_CDIS", PduRecorder.ENCODING_CDIS, "mismatched ENCODING_CDIS"); + assertEquals("ENCODING_JSON", PduRecorder.ENCODING_JSON, "mismatched ENCODING_JSON"); + } + + @Test + public void testEncodingOptionsList() + { + if (verbose) + System.out.println("*** PduRecorderTest testEncodingOptionsList()"); + + // trigger initialization by creating a recorder + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + assertNotNull(PduRecorder.ENCODING_OPTIONS_LIST, "ENCODING_OPTIONS_LIST should not be null"); + assertTrue(PduRecorder.ENCODING_OPTIONS_LIST.contains(PduRecorder.ENCODING_PLAINTEXT), "list should contain PLAINTEXT"); + assertTrue(PduRecorder.ENCODING_OPTIONS_LIST.contains(PduRecorder.ENCODING_BASE64), "list should contain BASE64"); + assertTrue(PduRecorder.ENCODING_OPTIONS_LIST.contains(PduRecorder.ENCODING_BINARY), "list should contain BINARY"); + } + + @Test + public void testCommentMarker() + { + if (verbose) + System.out.println("*** PduRecorderTest testCommentMarker()"); + + assertEquals("#", PduRecorder.COMMENT_MARKER, "mismatched comment marker"); + } + + @Test + public void testProgressiveSetters() + { + if (verbose) + System.out.println("*** PduRecorderTest testProgressiveSetters()"); + + // test fluent/progressive setter chaining + PduRecorder recorder = new PduRecorder("./testOutput", "239.1.2.3", 3000); + PduRecorder result = recorder + .setAddress("239.1.2.5") + .setPort(5000) + .setDescriptor("chained") + .setLogFileName("chained.dislog") + .setVerbose(false); + + assertNotNull(result, "progressive setter chain should return non-null"); + assertEquals("239.1.2.5", result.getAddress(), "mismatched address after chained set"); + assertEquals(5000, result.getPort(), "mismatched port after chained set"); + assertEquals("chained", result.getDescriptor(), "mismatched descriptor after chained set"); + assertEquals("chained.dislog", result.getLogFileName(), "mismatched log file name after chained set"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("PduRecorderTest start"); + PduRecorderTest test = new PduRecorderTest(); + setUpClass(); + test.testFullConstructor(); + test.testDefaultAddress(); + test.testDefaultPort(); + test.testSetAddress(); + test.testSetPort(); + test.testSetDescriptor(); + test.testDefaultEncoding(); + test.testSetEncodingBase64(); + test.testSetEncodingBinary(); + test.testUnsupportedEncodingIgnored(); + test.testSetLogFileName(); + test.testDefaultLogFileName(); + test.testSetOutputDirectory(); + test.testVerboseSettings(); + test.testVerboseReceiptSetting(); + test.testVerboseSendingSetting(); + test.testVerboseTimestampSetting(); + test.testReadableTimeStampSetting(); + test.testZeroBasedTimeStampSetting(); + test.testIncludeHeadersSetting(); + test.testEncodingConstants(); + test.testEncodingOptionsList(); + test.testCommentMarker(); + test.testProgressiveSetters(); + tearDownClass(); + System.out.println("PduRecorderTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/PointObjectStatePduTest.java b/test/edu/nps/moves/dis7/test/PointObjectStatePduTest.java new file mode 100644 index 0000000000..1681188c0e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/PointObjectStatePduTest.java @@ -0,0 +1,128 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ForceID; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EulerAngles; +import edu.nps.moves.dis7.pdus.ObjectType; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.PointObjectStatePdu; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.Vector3Double; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.PlatformDomain; +import edu.nps.moves.dis7.enumerations.ObjectKind; + +/** + * Unit tests for satisfactory handling of Point Object State PDU fields and values. + */ +@DisplayName("PointObjectStatePduTest") +public class PointObjectStatePduTest extends PduTest +{ + /** default constructor */ + public PointObjectStatePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** PointObjectStatePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** PointObjectStatePduTest testMultiplePdus()"); + + PointObjectStatePdu posPdu = pduFactory.makePointObjectStatePdu(); + + posPdu.setObjectID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + posPdu.setForceID(ForceID.FRIENDLY); + posPdu.setObjectType(new ObjectType().setDomain(PlatformDomain.LAND).setObjectKind(ObjectKind.OBSTACLE).setCategory((byte) 1)); + posPdu.setObjectLocation(new Vector3Double().setX(1000.0).setY(2000.0).setZ(3000.0)); + posPdu.setObjectOrientation(new EulerAngles().setPhi(0.1f).setTheta(0.2f).setPsi(0.3f)); + posPdu.setRequesterID(new SimulationAddress().setSite(1).setApplication(2)); + posPdu.setReceivingID(new SimulationAddress().setSite(3).setApplication(4)); + posPdu.setUpdateNumber(1); + testOnePdu(posPdu); + + posPdu.setObjectLocation(new Vector3Double().setX(4000.0).setY(5000.0).setZ(6000.0)); + posPdu.setUpdateNumber(2); + testOnePdu(posPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + PointObjectStatePdu createdCast = (PointObjectStatePdu) createdPdu; + PointObjectStatePdu receivedCast = (PointObjectStatePdu) receivedPdus.get(0); + + assertEquals(createdCast.getObjectID(), receivedCast.getObjectID(), "mismatched ObjectID"); + assertEquals(createdCast.getReferencedObjectID(), receivedCast.getReferencedObjectID(), "mismatched ReferencedObjectID"); + assertEquals(createdCast.getUpdateNumber(), receivedCast.getUpdateNumber(), "mismatched UpdateNumber"); + assertEquals(createdCast.getForceID(), receivedCast.getForceID(), "mismatched ForceID"); + assertEquals(createdCast.getModifications(), receivedCast.getModifications(), "mismatched Modifications"); + assertEquals(createdCast.getObjectType(), receivedCast.getObjectType(), "mismatched ObjectType"); + assertEquals(createdCast.getObjectLocation(), receivedCast.getObjectLocation(), "mismatched ObjectLocation"); + assertEquals(createdCast.getObjectOrientation(), receivedCast.getObjectOrientation(), "mismatched ObjectOrientation"); + assertEquals(createdCast.getSpecificObjectAppearance(), receivedCast.getSpecificObjectAppearance(), "mismatched SpecificObjectAppearance"); + assertEquals(createdCast.getGenerObjectAppearance(), receivedCast.getGenerObjectAppearance(), "mismatched GenerObjectAppearance"); + assertEquals(createdCast.getRequesterID(), receivedCast.getRequesterID(), "mismatched RequesterID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new PointObjectStatePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/QuaternionTest.java b/test/edu/nps/moves/dis7/test/QuaternionTest.java new file mode 100644 index 0000000000..4a564055e6 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/QuaternionTest.java @@ -0,0 +1,452 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.legacy.math.Quaternion; +import edu.nps.moves.legacy.math.Vec3f; +import edu.nps.moves.legacy.math.Matrix3f; +import edu.nps.moves.legacy.math.Matrix4f; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Quaternion legacy math class. + * Validates identity, axis-angle, Euler, matrix conversion, normalize, + * conjugate, invert, multiply, xform, slerp, and makeFromVecs. + */ +@DisplayName("QuaternionTest") +public class QuaternionTest +{ + private static final float TOLERANCE = 1.0e-4f; + private static boolean verbose = true; + + /** default constructor */ + public QuaternionTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** QuaternionTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** QuaternionTest tearDownClass()"); + } + + @Test + public void testDefaultConstructorIsIdentity() + { + if (verbose) + System.out.println("*** QuaternionTest testDefaultConstructorIsIdentity()"); + + Quaternion q = new Quaternion(); + assertEquals(0.0f, q.getQuatValue(0), TOLERANCE, "identity q[0]"); + assertEquals(0.0f, q.getQuatValue(1), TOLERANCE, "identity q[1]"); + assertEquals(0.0f, q.getQuatValue(2), TOLERANCE, "identity q[2]"); + assertEquals(1.0f, q.getQuatValue(3), TOLERANCE, "identity q[3]"); + } + + @Test + public void testIdentityLength() + { + if (verbose) + System.out.println("*** QuaternionTest testIdentityLength()"); + + Quaternion q = new Quaternion(); + assertEquals(1.0f, q.length(), TOLERANCE, "identity quaternion should have unit length"); + } + + @Test + public void testCopyConstructor() + { + if (verbose) + System.out.println("*** QuaternionTest testCopyConstructor()"); + + float[] axis = {0.0f, 0.0f, 1.0f}; + Quaternion original = new Quaternion(axis, (float)(Math.PI / 4.0)); + Quaternion copy = new Quaternion(original); + assertEquals(original.getQuatValue(0), copy.getQuatValue(0), TOLERANCE, "copy q[0]"); + assertEquals(original.getQuatValue(1), copy.getQuatValue(1), TOLERANCE, "copy q[1]"); + assertEquals(original.getQuatValue(2), copy.getQuatValue(2), TOLERANCE, "copy q[2]"); + assertEquals(original.getQuatValue(3), copy.getQuatValue(3), TOLERANCE, "copy q[3]"); + } + + @Test + public void testAxisAngleRoundTrip() + { + if (verbose) + System.out.println("*** QuaternionTest testAxisAngleRoundTrip()"); + + float angle = (float)(Math.PI / 3.0); // 60 degrees + float[] axisIn = {0.0f, 1.0f, 0.0f}; + Quaternion q = new Quaternion(axisIn, angle); + + float[] axisOut = new float[3]; + float[] angleOut = new float[1]; + q.getAxisAngle(axisOut, angleOut); + + assertEquals(0.0f, axisOut[0], TOLERANCE, "axis x"); + assertEquals(1.0f, axisOut[1], TOLERANCE, "axis y"); + assertEquals(0.0f, axisOut[2], TOLERANCE, "axis z"); + assertEquals(angle, angleOut[0], TOLERANCE, "angle"); + } + + @Test + public void testEulersRoundTrip() + { + if (verbose) + System.out.println("*** QuaternionTest testEulersRoundTrip()"); + + float heading = 0.5f; + float pitch = 0.3f; + float roll = 0.1f; + + Quaternion q = new Quaternion(); + q.setEulers(heading, pitch, roll); + + float[] hpr = new float[3]; + q.getEulers(hpr); + + assertEquals(heading, hpr[0], TOLERANCE, "heading round-trip"); + assertEquals(pitch, hpr[1], TOLERANCE, "pitch round-trip"); + assertEquals(roll, hpr[2], TOLERANCE, "roll round-trip"); + } + + @Test + public void testZeroEulersGiveIdentity() + { + if (verbose) + System.out.println("*** QuaternionTest testZeroEulersGiveIdentity()"); + + Quaternion q = new Quaternion(); + q.setEulers(0.0f, 0.0f, 0.0f); + assertEquals(0.0f, q.getQuatValue(0), TOLERANCE, "zero euler q[0]"); + assertEquals(0.0f, q.getQuatValue(1), TOLERANCE, "zero euler q[1]"); + assertEquals(0.0f, q.getQuatValue(2), TOLERANCE, "zero euler q[2]"); + assertEquals(1.0f, q.getQuatValue(3), TOLERANCE, "zero euler q[3]"); + } + + @Test + public void testMatrix3fRoundTrip() + { + if (verbose) + System.out.println("*** QuaternionTest testMatrix3fRoundTrip()"); + + Matrix3f mIn = new Matrix3f(0.5f, 0.3f, 0.1f); + Quaternion q = new Quaternion(mIn); + Matrix3f mOut = new Matrix3f(); + q.getMat3(mOut); + + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + assertEquals(mIn.getMatValue(r, c), mOut.getMatValue(r, c), TOLERANCE, + "matrix3f round-trip [" + r + "][" + c + "]"); + } + + @Test + public void testMatrix4fRoundTrip() + { + if (verbose) + System.out.println("*** QuaternionTest testMatrix4fRoundTrip()"); + + Matrix4f mIn = new Matrix4f(0.4f, 0.2f, 0.6f); + Quaternion q = new Quaternion(mIn); + Matrix4f mOut = new Matrix4f(); + q.getMat4(mOut); + + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) + assertEquals(mIn.getMatValue(r, c), mOut.getMatValue(r, c), TOLERANCE, + "matrix4f round-trip [" + r + "][" + c + "]"); + // bottom row and right column + assertEquals(0.0f, mOut.getMatValue(0, 3), TOLERANCE, "m[0][3]"); + assertEquals(0.0f, mOut.getMatValue(1, 3), TOLERANCE, "m[1][3]"); + assertEquals(0.0f, mOut.getMatValue(2, 3), TOLERANCE, "m[2][3]"); + assertEquals(0.0f, mOut.getMatValue(3, 0), TOLERANCE, "m[3][0]"); + assertEquals(0.0f, mOut.getMatValue(3, 1), TOLERANCE, "m[3][1]"); + assertEquals(0.0f, mOut.getMatValue(3, 2), TOLERANCE, "m[3][2]"); + assertEquals(1.0f, mOut.getMatValue(3, 3), TOLERANCE, "m[3][3]"); + } + + @Test + public void testNormalize() + { + if (verbose) + System.out.println("*** QuaternionTest testNormalize()"); + + Quaternion q = new Quaternion(); + q.setQuat(1.0f, 2.0f, 3.0f, 4.0f); + q.normalize(); + assertEquals(1.0f, q.length(), TOLERANCE, "normalized quaternion should have unit length"); + } + + @Test + public void testConjugate() + { + if (verbose) + System.out.println("*** QuaternionTest testConjugate()"); + + Quaternion q = new Quaternion(); + q.setQuat(1.0f, 2.0f, 3.0f, 4.0f); + q.conjugate(); + assertEquals(-1.0f, q.getQuatValue(0), TOLERANCE, "conjugate q[0]"); + assertEquals(-2.0f, q.getQuatValue(1), TOLERANCE, "conjugate q[1]"); + assertEquals(-3.0f, q.getQuatValue(2), TOLERANCE, "conjugate q[2]"); + assertEquals(4.0f, q.getQuatValue(3), TOLERANCE, "conjugate q[3]"); + } + + @Test + public void testInvertUnitQuaternion() + { + if (verbose) + System.out.println("*** QuaternionTest testInvertUnitQuaternion()"); + + // for unit quaternion, inverse equals conjugate + float[] axis = {0.0f, 0.0f, 1.0f}; + Quaternion q = new Quaternion(axis, (float)(Math.PI / 4.0)); + Quaternion inv = new Quaternion(q); + inv.invert(); + + // q * q^-1 should give identity + Quaternion result = new Quaternion(); + result.mult(q, inv); + assertEquals(0.0f, result.getQuatValue(0), TOLERANCE, "q*q^-1 q[0]"); + assertEquals(0.0f, result.getQuatValue(1), TOLERANCE, "q*q^-1 q[1]"); + assertEquals(0.0f, result.getQuatValue(2), TOLERANCE, "q*q^-1 q[2]"); + assertEquals(1.0f, result.getQuatValue(3), TOLERANCE, "q*q^-1 q[3]"); + } + + @Test + public void testMultiplyIdentity() + { + if (verbose) + System.out.println("*** QuaternionTest testMultiplyIdentity()"); + + Quaternion identity = new Quaternion(); + float[] axis = {1.0f, 0.0f, 0.0f}; + Quaternion q = new Quaternion(axis, (float)(Math.PI / 6.0)); + + Quaternion result = new Quaternion(); + result.mult(q, identity); + + assertEquals(q.getQuatValue(0), result.getQuatValue(0), TOLERANCE, "q*I q[0]"); + assertEquals(q.getQuatValue(1), result.getQuatValue(1), TOLERANCE, "q*I q[1]"); + assertEquals(q.getQuatValue(2), result.getQuatValue(2), TOLERANCE, "q*I q[2]"); + assertEquals(q.getQuatValue(3), result.getQuatValue(3), TOLERANCE, "q*I q[3]"); + } + + @Test + public void testXformIdentity() + { + if (verbose) + System.out.println("*** QuaternionTest testXformIdentity()"); + + Quaternion identity = new Quaternion(); + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + identity.xform(v); + assertEquals(1.0f, v.get(0), TOLERANCE, "identity xform v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "identity xform v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "identity xform v[2]"); + } + + @Test + public void testXform90DegreesAboutZ() + { + if (verbose) + System.out.println("*** QuaternionTest testXform90DegreesAboutZ()"); + + float[] axis = {0.0f, 0.0f, 1.0f}; + Quaternion q = new Quaternion(axis, (float)(Math.PI / 2.0)); + Vec3f v = new Vec3f(1.0f, 0.0f, 0.0f); + q.xform(v); + // rotating x-axis 90 degrees about z gives y-axis + assertEquals(0.0f, v.get(0), TOLERANCE, "rotated v[0]"); + assertEquals(1.0f, v.get(1), TOLERANCE, "rotated v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "rotated v[2]"); + } + + @Test + public void testXformArrayForm() + { + if (verbose) + System.out.println("*** QuaternionTest testXformArrayForm()"); + + float[] axis = {0.0f, 0.0f, 1.0f}; + Quaternion q = new Quaternion(axis, (float)(Math.PI / 2.0)); + float[] v = {1.0f, 0.0f, 0.0f}; + q.xform(v); + assertEquals(0.0f, v[0], TOLERANCE, "rotated v[0]"); + assertEquals(1.0f, v[1], TOLERANCE, "rotated v[1]"); + assertEquals(0.0f, v[2], TOLERANCE, "rotated v[2]"); + } + + @Test + public void testSlerpEndpoints() + { + if (verbose) + System.out.println("*** QuaternionTest testSlerpEndpoints()"); + + float[] axis = {0.0f, 1.0f, 0.0f}; + Quaternion q1 = new Quaternion(); + Quaternion q2 = new Quaternion(axis, (float)(Math.PI / 2.0)); + + // slerp at alpha=0 should give q1 + Quaternion result0 = new Quaternion(); + result0.slerp(q1, q2, 0.0f, 0); + assertEquals(q1.getQuatValue(0), result0.getQuatValue(0), TOLERANCE, "slerp(0) q[0]"); + assertEquals(q1.getQuatValue(1), result0.getQuatValue(1), TOLERANCE, "slerp(0) q[1]"); + assertEquals(q1.getQuatValue(2), result0.getQuatValue(2), TOLERANCE, "slerp(0) q[2]"); + assertEquals(q1.getQuatValue(3), result0.getQuatValue(3), TOLERANCE, "slerp(0) q[3]"); + + // slerp at alpha=1 should give q2 + Quaternion result1 = new Quaternion(); + result1.slerp(q1, q2, 1.0f, 0); + assertEquals(q2.getQuatValue(0), result1.getQuatValue(0), TOLERANCE, "slerp(1) q[0]"); + assertEquals(q2.getQuatValue(1), result1.getQuatValue(1), TOLERANCE, "slerp(1) q[1]"); + assertEquals(q2.getQuatValue(2), result1.getQuatValue(2), TOLERANCE, "slerp(1) q[2]"); + assertEquals(q2.getQuatValue(3), result1.getQuatValue(3), TOLERANCE, "slerp(1) q[3]"); + } + + @Test + public void testSlerpMidpoint() + { + if (verbose) + System.out.println("*** QuaternionTest testSlerpMidpoint()"); + + Quaternion q1 = new Quaternion(); + float[] axis = {0.0f, 1.0f, 0.0f}; + Quaternion q2 = new Quaternion(axis, (float)(Math.PI / 2.0)); + + Quaternion mid = new Quaternion(); + mid.slerp(q1, q2, 0.5f, 0); + // midpoint should have unit length + assertEquals(1.0f, mid.length(), TOLERANCE, "slerp midpoint should have unit length"); + } + + @Test + public void testMakeFromVecsParallel() + { + if (verbose) + System.out.println("*** QuaternionTest testMakeFromVecsParallel()"); + + Vec3f v1 = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f v2 = new Vec3f(1.0f, 0.0f, 0.0f); + Quaternion q = new Quaternion(v1, v2); + // parallel vectors should give identity quaternion + assertEquals(0.0f, q.getQuatValue(0), TOLERANCE, "parallel q[0]"); + assertEquals(0.0f, q.getQuatValue(1), TOLERANCE, "parallel q[1]"); + assertEquals(0.0f, q.getQuatValue(2), TOLERANCE, "parallel q[2]"); + assertEquals(1.0f, q.getQuatValue(3), TOLERANCE, "parallel q[3]"); + } + + @Test + public void testMakeFromVecsOrthogonal() + { + if (verbose) + System.out.println("*** QuaternionTest testMakeFromVecsOrthogonal()"); + + Vec3f v1 = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f v2 = new Vec3f(0.0f, 1.0f, 0.0f); + Quaternion q = new Quaternion(v1, v2); + // rotating v1 by q should give v2 + Vec3f test = new Vec3f(1.0f, 0.0f, 0.0f); + q.xform(test); + assertEquals(0.0f, test.get(0), TOLERANCE, "rotated v[0]"); + assertEquals(1.0f, test.get(1), TOLERANCE, "rotated v[1]"); + assertEquals(0.0f, test.get(2), TOLERANCE, "rotated v[2]"); + } + + @Test + public void testSetGetQuatValue() + { + if (verbose) + System.out.println("*** QuaternionTest testSetGetQuatValue()"); + + Quaternion q = new Quaternion(); + q.setQuatValue(0, 0.5f); + q.setQuatValue(1, 0.6f); + q.setQuatValue(2, 0.7f); + q.setQuatValue(3, 0.8f); + assertEquals(0.5f, q.getQuatValue(0), TOLERANCE, "get q[0]"); + assertEquals(0.6f, q.getQuatValue(1), TOLERANCE, "get q[1]"); + assertEquals(0.7f, q.getQuatValue(2), TOLERANCE, "get q[2]"); + assertEquals(0.8f, q.getQuatValue(3), TOLERANCE, "get q[3]"); + } + + @Test + public void testBoundsCheck() + { + if (verbose) + System.out.println("*** QuaternionTest testBoundsCheck()"); + + Quaternion q = new Quaternion(); + assertEquals(0.0f, q.getQuatValue(-1), TOLERANCE, "out of bounds should return 0"); + assertEquals(0.0f, q.getQuatValue(4), TOLERANCE, "out of bounds should return 0"); + } + + @Test + public void testAddSub() + { + if (verbose) + System.out.println("*** QuaternionTest testAddSub()"); + + Quaternion a = new Quaternion(); + a.setQuat(1.0f, 2.0f, 3.0f, 4.0f); + Quaternion b = new Quaternion(); + b.setQuat(5.0f, 6.0f, 7.0f, 8.0f); + + Quaternion sum = new Quaternion(); + sum.add(a, b); + assertEquals(6.0f, sum.getQuatValue(0), TOLERANCE, "add q[0]"); + assertEquals(8.0f, sum.getQuatValue(1), TOLERANCE, "add q[1]"); + assertEquals(10.0f, sum.getQuatValue(2), TOLERANCE, "add q[2]"); + assertEquals(12.0f, sum.getQuatValue(3), TOLERANCE, "add q[3]"); + + Quaternion diff = new Quaternion(); + diff.sub(b, a); + assertEquals(4.0f, diff.getQuatValue(0), TOLERANCE, "sub q[0]"); + assertEquals(4.0f, diff.getQuatValue(1), TOLERANCE, "sub q[1]"); + assertEquals(4.0f, diff.getQuatValue(2), TOLERANCE, "sub q[2]"); + assertEquals(4.0f, diff.getQuatValue(3), TOLERANCE, "sub q[3]"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("QuaternionTest start"); + QuaternionTest test = new QuaternionTest(); + setUpClass(); + test.testDefaultConstructorIsIdentity(); + test.testIdentityLength(); + test.testCopyConstructor(); + test.testAxisAngleRoundTrip(); + test.testEulersRoundTrip(); + test.testZeroEulersGiveIdentity(); + test.testMatrix3fRoundTrip(); + test.testMatrix4fRoundTrip(); + test.testNormalize(); + test.testConjugate(); + test.testInvertUnitQuaternion(); + test.testMultiplyIdentity(); + test.testXformIdentity(); + test.testXform90DegreesAboutZ(); + test.testXformArrayForm(); + test.testSlerpEndpoints(); + test.testSlerpMidpoint(); + test.testMakeFromVecsParallel(); + test.testMakeFromVecsOrthogonal(); + test.testSetGetQuatValue(); + test.testBoundsCheck(); + test.testAddSub(); + tearDownClass(); + System.out.println("QuaternionTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/RangeCoordinatesTest.java b/test/edu/nps/moves/dis7/test/RangeCoordinatesTest.java new file mode 100644 index 0000000000..7c60b2812e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RangeCoordinatesTest.java @@ -0,0 +1,287 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.spatial.RangeCoordinates; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for RangeCoordinates spatial utility class. + * Validates DIS global to local tangent plane conversion, local to DIS global conversion, + * round-trip accuracy, and known reference point validation using WGS-84 geodesy. + */ +@DisplayName("RangeCoordinatesTest") +public class RangeCoordinatesTest +{ + /** WGS-84 semi-major axis in meters */ + private static final double WGS84_SEMI_MAJOR_AXIS = 6378137.0; + + /** WGS-84 semi-minor axis in meters */ + private static final double WGS84_SEMI_MINOR_AXIS = 6356752.3142; + + /** Tolerance for coordinate conversions in meters (1 millimeter) */ + private static final double TOLERANCE_METERS = 0.001; + + /** Tolerance for round-trip conversions in meters (1 centimeter, accounts for accumulated floating-point error) */ + private static final double ROUND_TRIP_TOLERANCE = 0.01; + + private static boolean verbose = true; + + /** default constructor */ + public RangeCoordinatesTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest tearDownClass()"); + } + + @Test + public void testConstructorPrimeMeridianEquator() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testConstructorPrimeMeridianEquator()"); + + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + assertNotNull(rc, "RangeCoordinates at equator/prime meridian should not be null"); + } + + @Test + public void testConstructorArbitraryLocation() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testConstructorArbitraryLocation()"); + + RangeCoordinates rc = new RangeCoordinates(36.6, -121.9, 10.0); + assertNotNull(rc, "RangeCoordinates at Monterey-area location should not be null"); + } + + @Test + public void testDISCoordFromLocalFlatAtOriginPrimeMeridian() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testDISCoordFromLocalFlatAtOriginPrimeMeridian()"); + + // At equator/prime meridian (lat=0, lon=0, alt=0), the local origin (0,0,0) + // should map to DIS geocentric coordinates approximately (6378137, 0, 0) + // which is the WGS-84 semi-major axis along the x-axis + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + Vector3Double disCoord = rc.DISCoordFromLocalFlat(0.0, 0.0, 0.0); + + assertNotNull(disCoord, "DIS coordinate should not be null"); + assertEquals(WGS84_SEMI_MAJOR_AXIS, disCoord.getX(), TOLERANCE_METERS, "mismatched DIS x at equator/prime meridian"); + assertEquals(0.0, disCoord.getY(), TOLERANCE_METERS, "mismatched DIS y at equator/prime meridian"); + assertEquals(0.0, disCoord.getZ(), TOLERANCE_METERS, "mismatched DIS z at equator/prime meridian"); + } + + @Test + public void testDISCoordFromLocalFlatAtEquator90East() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testDISCoordFromLocalFlatAtEquator90East()"); + + // At equator/90-deg-east (lat=0, lon=90, alt=0), the local origin + // should map to DIS geocentric coordinates approximately (0, 6378137, 0) + RangeCoordinates rc = new RangeCoordinates(0.0, 90.0, 0.0); + Vector3Double disCoord = rc.DISCoordFromLocalFlat(0.0, 0.0, 0.0); + + assertNotNull(disCoord, "DIS coordinate should not be null"); + assertEquals(0.0, disCoord.getX(), TOLERANCE_METERS, "mismatched DIS x at equator/90E"); + assertEquals(WGS84_SEMI_MAJOR_AXIS, disCoord.getY(), TOLERANCE_METERS, "mismatched DIS y at equator/90E"); + assertEquals(0.0, disCoord.getZ(), TOLERANCE_METERS, "mismatched DIS z at equator/90E"); + } + + @Test + public void testDISCoordFromLocalFlatAtNorthPole() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testDISCoordFromLocalFlatAtNorthPole()"); + + // At north pole (lat=90, lon=0, alt=0), the local origin + // should map to DIS geocentric coordinates approximately (0, 0, 6356752.3142) + // which is the WGS-84 semi-minor axis along the z-axis + RangeCoordinates rc = new RangeCoordinates(90.0, 0.0, 0.0); + Vector3Double disCoord = rc.DISCoordFromLocalFlat(0.0, 0.0, 0.0); + + assertNotNull(disCoord, "DIS coordinate should not be null"); + assertEquals(0.0, disCoord.getX(), TOLERANCE_METERS, "mismatched DIS x at north pole"); + assertEquals(0.0, disCoord.getY(), TOLERANCE_METERS, "mismatched DIS y at north pole"); + assertEquals(WGS84_SEMI_MINOR_AXIS, disCoord.getZ(), TOLERANCE_METERS, "mismatched DIS z at north pole"); + } + + @Test + public void testLocalCoordFromDisAtOriginPrimeMeridian() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testLocalCoordFromDisAtOriginPrimeMeridian()"); + + // DIS geocentric (6378137, 0, 0) should map back to local origin (0,0,0) + // when the range is centered at equator/prime meridian + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + Vector3Double localCoord = rc.localCoordFromDis(WGS84_SEMI_MAJOR_AXIS, 0.0, 0.0); + + assertNotNull(localCoord, "local coordinate should not be null"); + assertEquals(0.0, localCoord.getX(), TOLERANCE_METERS, "mismatched local x from DIS origin"); + assertEquals(0.0, localCoord.getY(), TOLERANCE_METERS, "mismatched local y from DIS origin"); + assertEquals(0.0, localCoord.getZ(), TOLERANCE_METERS, "mismatched local z from DIS origin"); + } + + @Test + public void testRoundTripLocalToDISAndBack() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testRoundTripLocalToDISAndBack()"); + + // Create range at Monterey area + RangeCoordinates rc = new RangeCoordinates(36.6, -121.9, 10.0); + + double localX = 500.0; + double localY = -300.0; + double localZ = 50.0; + + // Convert local to DIS + Vector3Double disCoord = rc.DISCoordFromLocalFlat(localX, localY, localZ); + assertNotNull(disCoord, "DIS coordinate should not be null"); + + // Convert DIS back to local + Vector3Double roundTrip = rc.localCoordFromDis(disCoord.getX(), disCoord.getY(), disCoord.getZ()); + assertNotNull(roundTrip, "round-trip local coordinate should not be null"); + + assertEquals(localX, roundTrip.getX(), ROUND_TRIP_TOLERANCE, "mismatched round-trip x"); + assertEquals(localY, roundTrip.getY(), ROUND_TRIP_TOLERANCE, "mismatched round-trip y"); + assertEquals(localZ, roundTrip.getZ(), ROUND_TRIP_TOLERANCE, "mismatched round-trip z"); + } + + @Test + public void testRoundTripDISToLocalAndBack() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testRoundTripDISToLocalAndBack()"); + + // Use range at equator/prime meridian + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + + // A point slightly offset from the surface along x-axis + double disX = WGS84_SEMI_MAJOR_AXIS + 100.0; + double disY = 200.0; + double disZ = 300.0; + + // Convert DIS to local + Vector3Double localCoord = rc.localCoordFromDis(disX, disY, disZ); + assertNotNull(localCoord, "local coordinate should not be null"); + + // Convert local back to DIS + Vector3Double roundTrip = rc.DISCoordFromLocalFlat(localCoord.getX(), localCoord.getY(), localCoord.getZ()); + assertNotNull(roundTrip, "round-trip DIS coordinate should not be null"); + + assertEquals(disX, roundTrip.getX(), ROUND_TRIP_TOLERANCE, "mismatched round-trip DIS x"); + assertEquals(disY, roundTrip.getY(), ROUND_TRIP_TOLERANCE, "mismatched round-trip DIS y"); + assertEquals(disZ, roundTrip.getZ(), ROUND_TRIP_TOLERANCE, "mismatched round-trip DIS z"); + } + + @Test + public void testChangeVectorToDisCoordFromLocalFlat() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testChangeVectorToDisCoordFromLocalFlat()"); + + // Verify that the in-place conversion method produces the same result + // as the returning method + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + + Vector3Double expected = rc.DISCoordFromLocalFlat(0.0, 0.0, 0.0); + assertNotNull(expected, "expected DIS coordinate should not be null"); + + Vector3Double inPlace = new Vector3Double(); + inPlace.setX(0.0); + inPlace.setY(0.0); + inPlace.setZ(0.0); + rc.changeVectorToDisCoordFromLocalFlat(inPlace); + + assertEquals(expected.getX(), inPlace.getX(), TOLERANCE_METERS, "mismatched in-place DIS x"); + assertEquals(expected.getY(), inPlace.getY(), TOLERANCE_METERS, "mismatched in-place DIS y"); + assertEquals(expected.getZ(), inPlace.getZ(), TOLERANCE_METERS, "mismatched in-place DIS z"); + } + + @Test + public void testChangeVectorToLocalCoordFromDIS() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testChangeVectorToLocalCoordFromDIS()"); + + // Verify that the in-place conversion method produces the same result + // as the returning method + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + + Vector3Double expected = rc.localCoordFromDis(WGS84_SEMI_MAJOR_AXIS, 0.0, 0.0); + assertNotNull(expected, "expected local coordinate should not be null"); + + Vector3Double inPlace = new Vector3Double(); + inPlace.setX(WGS84_SEMI_MAJOR_AXIS); + inPlace.setY(0.0); + inPlace.setZ(0.0); + rc.changeVectorToLocalCoordFromDIS(inPlace); + + assertEquals(expected.getX(), inPlace.getX(), TOLERANCE_METERS, "mismatched in-place local x"); + assertEquals(expected.getY(), inPlace.getY(), TOLERANCE_METERS, "mismatched in-place local y"); + assertEquals(expected.getZ(), inPlace.getZ(), TOLERANCE_METERS, "mismatched in-place local z"); + } + + @Test + public void testLocalOffsetProducesNonZeroDISDelta() + { + if (verbose) + System.out.println("*** RangeCoordinatesTest testLocalOffsetProducesNonZeroDISDelta()"); + + RangeCoordinates rc = new RangeCoordinates(0.0, 0.0, 0.0); + + Vector3Double origin = rc.DISCoordFromLocalFlat(0.0, 0.0, 0.0); + Vector3Double offset = rc.DISCoordFromLocalFlat(1000.0, 0.0, 0.0); + + assertNotNull(origin, "origin DIS coordinate should not be null"); + assertNotNull(offset, "offset DIS coordinate should not be null"); + + // A 1000m east offset should produce a different DIS coordinate + double distance = Math.sqrt( + Math.pow(offset.getX() - origin.getX(), 2) + + Math.pow(offset.getY() - origin.getY(), 2) + + Math.pow(offset.getZ() - origin.getZ(), 2)); + assertTrue(distance > 900.0, "1000m local offset should produce significant DIS coordinate change"); + assertTrue(distance < 1100.0, "1000m local offset should not exceed expected DIS coordinate change"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("RangeCoordinatesTest start"); + RangeCoordinatesTest test = new RangeCoordinatesTest(); + setUpClass(); + test.testConstructorPrimeMeridianEquator(); + test.testConstructorArbitraryLocation(); + test.testDISCoordFromLocalFlatAtOriginPrimeMeridian(); + test.testDISCoordFromLocalFlatAtEquator90East(); + test.testDISCoordFromLocalFlatAtNorthPole(); + test.testLocalCoordFromDisAtOriginPrimeMeridian(); + test.testRoundTripLocalToDISAndBack(); + test.testRoundTripDISToLocalAndBack(); + test.testChangeVectorToDisCoordFromLocalFlat(); + test.testChangeVectorToLocalCoordFromDIS(); + test.testLocalOffsetProducesNonZeroDISDelta(); + tearDownClass(); + System.out.println("RangeCoordinatesTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/ReceiverPduTest.java b/test/edu/nps/moves/dis7/test/ReceiverPduTest.java new file mode 100644 index 0000000000..71c3438e2e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ReceiverPduTest.java @@ -0,0 +1,111 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ReceiverReceiverState; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.ReceiverPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Receiver PDU fields and values. + */ +@DisplayName("ReceiverPduTest") +public class ReceiverPduTest extends PduTest +{ + /** default constructor */ + public ReceiverPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ReceiverPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ReceiverPduTest testMultiplePdus()"); + + ReceiverPdu receiverPdu = pduFactory.makeReceiverPdu(); + + receiverPdu.setReceiverState(ReceiverReceiverState.ON_BUT_NOT_RECEIVING); + receiverPdu.setReceivedPower(50.0f); + receiverPdu.setTransmitterEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + receiverPdu.setTransmitterRadioId((short) 1); + testOnePdu(receiverPdu); + + receiverPdu.setReceiverState(ReceiverReceiverState.ON_AND_RECEIVING); + receiverPdu.setReceivedPower(75.0f); + testOnePdu(receiverPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ReceiverPdu createdCast = (ReceiverPdu) createdPdu; + ReceiverPdu receivedCast = (ReceiverPdu) receivedPdus.get(0); + + assertEquals(createdCast.getHeader(), receivedCast.getHeader(), "mismatched Header"); + assertEquals(createdCast.getReceiverState(), receivedCast.getReceiverState(), "mismatched ReceiverState"); + assertEquals(createdCast.getReceivedPower(), receivedCast.getReceivedPower(), "mismatched ReceivedPower"); + assertEquals(createdCast.getTransmitterEntityId(), receivedCast.getTransmitterEntityId(), "mismatched TransmitterEntityId"); + assertEquals(createdCast.getTransmitterRadioId(), receivedCast.getTransmitterRadioId(), "mismatched TransmitterRadioId"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ReceiverPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RecordQueryReliablePduTest.java b/test/edu/nps/moves/dis7/test/RecordQueryReliablePduTest.java new file mode 100644 index 0000000000..0a5465b286 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RecordQueryReliablePduTest.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RecordQueryREventType; +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RecordQueryReliablePdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Record Query Reliable PDU fields and values. + */ +@DisplayName("RecordQueryReliablePduTest") +public class RecordQueryReliablePduTest extends PduTest +{ + /** default constructor */ + public RecordQueryReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RecordQueryReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RecordQueryReliablePduTest testMultiplePdus()"); + + RecordQueryReliablePdu rqrPdu = pduFactory.makeRecordQueryReliablePdu(); + + rqrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + rqrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + rqrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + rqrPdu.setRequestID(1301); + rqrPdu.setEventType(RecordQueryREventType.PERIODIC); + rqrPdu.setTime(30000); + testOnePdu(rqrPdu); + + rqrPdu.setRequestID(1302); + rqrPdu.setEventType(RecordQueryREventType.INTERNAL_ENTITY_STATE_DATA); + rqrPdu.setTime(60000); + testOnePdu(rqrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + RecordQueryReliablePdu createdCast = (RecordQueryReliablePdu) createdPdu; + RecordQueryReliablePdu receivedCast = (RecordQueryReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getEventType(), receivedCast.getEventType(), "mismatched EventType"); + assertEquals(createdCast.getTime(), receivedCast.getTime(), "mismatched Time"); + assertEquals(createdCast.getRecordIDs(), receivedCast.getRecordIDs(), "mismatched RecordIDs"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new RecordQueryReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RecordReliablePduTest.java b/test/edu/nps/moves/dis7/test/RecordReliablePduTest.java new file mode 100644 index 0000000000..c2f7ea90c0 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RecordReliablePduTest.java @@ -0,0 +1,114 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RecordREventType; +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RecordReliablePdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Record Reliable PDU fields and values. + */ +@DisplayName("RecordReliablePduTest") +public class RecordReliablePduTest extends PduTest +{ + /** default constructor */ + public RecordReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RecordReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RecordReliablePduTest testMultiplePdus()"); + + RecordReliablePdu rrPdu = pduFactory.makeRecordReliablePdu(); + + rrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + rrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + rrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + rrPdu.setRequestID(1101); + rrPdu.setEventType(RecordREventType.OTHER); + testOnePdu(rrPdu); + + rrPdu.setRequestID(1102); + testOnePdu(rrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + RecordReliablePdu createdCast = (RecordReliablePdu) createdPdu; + RecordReliablePdu receivedCast = (RecordReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getEventType(), receivedCast.getEventType(), "mismatched EventType"); + assertEquals(createdCast.getRecordSets(), receivedCast.getRecordSets(), "mismatched RecordSets"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new RecordReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RemoveEntityPduTest.java b/test/edu/nps/moves/dis7/test/RemoveEntityPduTest.java new file mode 100644 index 0000000000..70989c74f0 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RemoveEntityPduTest.java @@ -0,0 +1,118 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RemoveEntityPdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Remove Entity PDU fields and values. + */ +@DisplayName("RemoveEntityPduTest") +public class RemoveEntityPduTest extends PduTest +{ + /** default constructor */ + public RemoveEntityPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RemoveEntityPduTest setUpClass()"); + + // superclass automatically setUp(), which includes setupNetwork() + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RemoveEntityPduTest testMultiplePdus()"); + + RemoveEntityPdu removeEntityPdu = pduFactory.makeRemoveEntityPdu(); + + removeEntityPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + removeEntityPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + removeEntityPdu.setRequestID(2001); + testOnePdu(removeEntityPdu); + + removeEntityPdu.setRequestID(2002); + testOnePdu(removeEntityPdu); + + // TODO additional PDU-specific tests + // TODO test various alternate constructors and utility methods + } + + /** Test single PDU for correctness according to all contained fields in this PDU type + * See https://en.wikipedia.org/wiki/Marshalling_(computer_science) + * @param createdPdu separate PDU for comparison + */ + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); // shared tests in superclass + + // can cast PDUs at this point since PduType matched + RemoveEntityPdu createdRemoveEntityPdu = (RemoveEntityPdu) createdPdu; + RemoveEntityPdu receivedRemoveEntityPdu = (RemoveEntityPdu) receivedPdus.get(0); // TODO might be more than one on receivedPdus list + + assertEquals(createdRemoveEntityPdu.getOriginatingID(), receivedRemoveEntityPdu.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdRemoveEntityPdu.getReceivingID(), receivedRemoveEntityPdu.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdRemoveEntityPdu.getRequestID(), receivedRemoveEntityPdu.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); // shared tests in superclass + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest removeEntityPduTest = new RemoveEntityPduTest(); + + removeEntityPduTest.setUp(); + removeEntityPduTest.testMultiplePdus(); + removeEntityPduTest.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RemoveEntityReliablePduTest.java b/test/edu/nps/moves/dis7/test/RemoveEntityReliablePduTest.java new file mode 100644 index 0000000000..16feb10963 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RemoveEntityReliablePduTest.java @@ -0,0 +1,111 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RemoveEntityReliablePdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Remove Entity Reliable PDU fields and values. + */ +@DisplayName("RemoveEntityReliablePduTest") +public class RemoveEntityReliablePduTest extends PduTest +{ + /** default constructor */ + public RemoveEntityReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RemoveEntityReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RemoveEntityReliablePduTest testMultiplePdus()"); + + RemoveEntityReliablePdu rerPdu = pduFactory.makeRemoveEntityReliablePdu(); + + rerPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + rerPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + rerPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + rerPdu.setRequestID(201); + testOnePdu(rerPdu); + + rerPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + rerPdu.setRequestID(202); + testOnePdu(rerPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + RemoveEntityReliablePdu createdCast = (RemoveEntityReliablePdu) createdPdu; + RemoveEntityReliablePdu receivedCast = (RemoveEntityReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new RemoveEntityReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RepairCompletePduTest.java b/test/edu/nps/moves/dis7/test/RepairCompletePduTest.java new file mode 100644 index 0000000000..59a47163c3 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RepairCompletePduTest.java @@ -0,0 +1,107 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RepairCompleteRepair; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RepairCompletePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Repair Complete PDU fields and values. + */ +@DisplayName("RepairCompletePduTest") +public class RepairCompletePduTest extends PduTest +{ + /** default constructor */ + public RepairCompletePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RepairCompletePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RepairCompletePduTest testMultiplePdus()"); + + RepairCompletePdu repairCompletePdu = pduFactory.makeRepairCompletePdu(); + + repairCompletePdu.setReceivingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + repairCompletePdu.setRepairingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + repairCompletePdu.setRepair(RepairCompleteRepair.ALL_REQUESTED_REPAIRS_PERFORMED); + testOnePdu(repairCompletePdu); + + repairCompletePdu.setRepair(RepairCompleteRepair.MOTOR_ENGINE); + testOnePdu(repairCompletePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + RepairCompletePdu createdCast = (RepairCompletePdu) createdPdu; + RepairCompletePdu receivedCast = (RepairCompletePdu) receivedPdus.get(0); + + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getRepairingEntityID(), receivedCast.getRepairingEntityID(), "mismatched RepairingEntityID"); + assertEquals(createdCast.getRepair(), receivedCast.getRepair(), "mismatched Repair"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new RepairCompletePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/RepairResponsePduTest.java b/test/edu/nps/moves/dis7/test/RepairResponsePduTest.java new file mode 100644 index 0000000000..1dd8e85d18 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/RepairResponsePduTest.java @@ -0,0 +1,107 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RepairResponseRepairResult; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.RepairResponsePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Repair Response PDU fields and values. + */ +@DisplayName("RepairResponsePduTest") +public class RepairResponsePduTest extends PduTest +{ + /** default constructor */ + public RepairResponsePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** RepairResponsePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** RepairResponsePduTest testMultiplePdus()"); + + RepairResponsePdu repairResponsePdu = pduFactory.makeRepairResponsePdu(); + + repairResponsePdu.setReceivingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + repairResponsePdu.setRepairingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + repairResponsePdu.setRepairResult(RepairResponseRepairResult.REPAIR_ENDED); + testOnePdu(repairResponsePdu); + + repairResponsePdu.setRepairResult(RepairResponseRepairResult.INVALID_REPAIR); + testOnePdu(repairResponsePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + RepairResponsePdu createdCast = (RepairResponsePdu) createdPdu; + RepairResponsePdu receivedCast = (RepairResponsePdu) receivedPdus.get(0); + + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getRepairingEntityID(), receivedCast.getRepairingEntityID(), "mismatched RepairingEntityID"); + assertEquals(createdCast.getRepairResult(), receivedCast.getRepairResult(), "mismatched RepairResult"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new RepairResponsePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ResupplyCancelPduTest.java b/test/edu/nps/moves/dis7/test/ResupplyCancelPduTest.java new file mode 100644 index 0000000000..9d3e3edf7a --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ResupplyCancelPduTest.java @@ -0,0 +1,104 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.ResupplyCancelPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Resupply Cancel PDU fields and values. + */ +@DisplayName("ResupplyCancelPduTest") +public class ResupplyCancelPduTest extends PduTest +{ + /** default constructor */ + public ResupplyCancelPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ResupplyCancelPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ResupplyCancelPduTest testMultiplePdus()"); + + ResupplyCancelPdu resupplyCancelPdu = pduFactory.makeResupplyCancelPdu(); + + resupplyCancelPdu.setReceivingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + resupplyCancelPdu.setSupplyingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + testOnePdu(resupplyCancelPdu); + + resupplyCancelPdu.setReceivingEntityID(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + testOnePdu(resupplyCancelPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ResupplyCancelPdu createdCast = (ResupplyCancelPdu) createdPdu; + ResupplyCancelPdu receivedCast = (ResupplyCancelPdu) receivedPdus.get(0); + + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getSupplyingEntityID(), receivedCast.getSupplyingEntityID(), "mismatched SupplyingEntityID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ResupplyCancelPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ResupplyOfferPduTest.java b/test/edu/nps/moves/dis7/test/ResupplyOfferPduTest.java new file mode 100644 index 0000000000..642c2fbcb1 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ResupplyOfferPduTest.java @@ -0,0 +1,107 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.ResupplyOfferPdu; +import edu.nps.moves.dis7.pdus.SupplyQuantity; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Resupply Offer PDU fields and values. + */ +@DisplayName("ResupplyOfferPduTest") +public class ResupplyOfferPduTest extends PduTest +{ + /** default constructor */ + public ResupplyOfferPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ResupplyOfferPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ResupplyOfferPduTest testMultiplePdus()"); + + ResupplyOfferPdu resupplyOfferPdu = pduFactory.makeResupplyOfferPdu(); + + resupplyOfferPdu.setReceivingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + resupplyOfferPdu.setSupplyingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + resupplyOfferPdu.getSupplies().add(new SupplyQuantity().setQuantity(50.0f)); + testOnePdu(resupplyOfferPdu); + + resupplyOfferPdu.getSupplies().add(new SupplyQuantity().setQuantity(75.0f)); + testOnePdu(resupplyOfferPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ResupplyOfferPdu createdCast = (ResupplyOfferPdu) createdPdu; + ResupplyOfferPdu receivedCast = (ResupplyOfferPdu) receivedPdus.get(0); + + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getSupplyingEntityID(), receivedCast.getSupplyingEntityID(), "mismatched SupplyingEntityID"); + assertEquals(createdCast.getSupplies(), receivedCast.getSupplies(), "mismatched Supplies"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ResupplyOfferPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ResupplyReceivedPduTest.java b/test/edu/nps/moves/dis7/test/ResupplyReceivedPduTest.java new file mode 100644 index 0000000000..0373362028 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ResupplyReceivedPduTest.java @@ -0,0 +1,107 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.ResupplyReceivedPdu; +import edu.nps.moves.dis7.pdus.SupplyQuantity; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Resupply Received PDU fields and values. + */ +@DisplayName("ResupplyReceivedPduTest") +public class ResupplyReceivedPduTest extends PduTest +{ + /** default constructor */ + public ResupplyReceivedPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ResupplyReceivedPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ResupplyReceivedPduTest testMultiplePdus()"); + + ResupplyReceivedPdu resupplyReceivedPdu = pduFactory.makeResupplyReceivedPdu(); + + resupplyReceivedPdu.setReceivingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + resupplyReceivedPdu.setSupplyingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + resupplyReceivedPdu.getSupplies().add(new SupplyQuantity().setQuantity(200.0f)); + testOnePdu(resupplyReceivedPdu); + + resupplyReceivedPdu.getSupplies().add(new SupplyQuantity().setQuantity(300.0f)); + testOnePdu(resupplyReceivedPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ResupplyReceivedPdu createdCast = (ResupplyReceivedPdu) createdPdu; + ResupplyReceivedPdu receivedCast = (ResupplyReceivedPdu) receivedPdus.get(0); + + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getSupplyingEntityID(), receivedCast.getSupplyingEntityID(), "mismatched SupplyingEntityID"); + assertEquals(createdCast.getSupplies(), receivedCast.getSupplies(), "mismatched Supplies"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ResupplyReceivedPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/SEESPduTest.java b/test/edu/nps/moves/dis7/test/SEESPduTest.java new file mode 100644 index 0000000000..8f80a9fa1c --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SEESPduTest.java @@ -0,0 +1,111 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SEESPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of SEES (Supplemental Emission Entity State) PDU fields and values. + */ +@DisplayName("SEESPduTest") +public class SEESPduTest extends PduTest +{ + /** default constructor */ + public SEESPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** SEESPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** SEESPduTest testMultiplePdus()"); + + SEESPdu seesPdu = pduFactory.makeSeesPdu(); + + seesPdu.setOrginatingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + seesPdu.setInfraredSignatureRepresentationIndex((short) 1); + seesPdu.setAcousticSignatureRepresentationIndex((short) 2); + seesPdu.setRadarCrossSectionSignatureRepresentationIndex((short) 3); + testOnePdu(seesPdu); + + seesPdu.setInfraredSignatureRepresentationIndex((short) 10); + seesPdu.setAcousticSignatureRepresentationIndex((short) 20); + testOnePdu(seesPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + SEESPdu createdCast = (SEESPdu) createdPdu; + SEESPdu receivedCast = (SEESPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOrginatingEntityID(), receivedCast.getOrginatingEntityID(), "mismatched OrginatingEntityID"); + assertEquals(createdCast.getInfraredSignatureRepresentationIndex(), receivedCast.getInfraredSignatureRepresentationIndex(), "mismatched InfraredSignatureRepresentationIndex"); + assertEquals(createdCast.getAcousticSignatureRepresentationIndex(), receivedCast.getAcousticSignatureRepresentationIndex(), "mismatched AcousticSignatureRepresentationIndex"); + assertEquals(createdCast.getRadarCrossSectionSignatureRepresentationIndex(), receivedCast.getRadarCrossSectionSignatureRepresentationIndex(), "mismatched RadarCrossSectionSignatureRepresentationIndex"); + assertEquals(createdCast.getPropulsionSystemData(), receivedCast.getPropulsionSystemData(), "mismatched PropulsionSystemData"); + assertEquals(createdCast.getVectoringSystemData(), receivedCast.getVectoringSystemData(), "mismatched VectoringSystemData"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new SEESPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/ServiceRequestPduTest.java b/test/edu/nps/moves/dis7/test/ServiceRequestPduTest.java new file mode 100644 index 0000000000..77296257ff --- /dev/null +++ b/test/edu/nps/moves/dis7/test/ServiceRequestPduTest.java @@ -0,0 +1,110 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.ServiceRequestServiceTypeRequested; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.ServiceRequestPdu; +import edu.nps.moves.dis7.pdus.SupplyQuantity; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Service Request PDU fields and values. + */ +@DisplayName("ServiceRequestPduTest") +public class ServiceRequestPduTest extends PduTest +{ + /** default constructor */ + public ServiceRequestPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** ServiceRequestPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** ServiceRequestPduTest testMultiplePdus()"); + + ServiceRequestPdu serviceRequestPdu = pduFactory.makeServiceRequestPdu(); + + serviceRequestPdu.setRequestingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + serviceRequestPdu.setServicingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + serviceRequestPdu.setServiceTypeRequested(ServiceRequestServiceTypeRequested.RESUPPLY); + serviceRequestPdu.getSupplies().add(new SupplyQuantity().setQuantity(100.0f)); + testOnePdu(serviceRequestPdu); + + serviceRequestPdu.setServiceTypeRequested(ServiceRequestServiceTypeRequested.REPAIR); + testOnePdu(serviceRequestPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + ServiceRequestPdu createdCast = (ServiceRequestPdu) createdPdu; + ServiceRequestPdu receivedCast = (ServiceRequestPdu) receivedPdus.get(0); + + assertEquals(createdCast.getRequestingEntityID(), receivedCast.getRequestingEntityID(), "mismatched RequestingEntityID"); + assertEquals(createdCast.getServicingEntityID(), receivedCast.getServicingEntityID(), "mismatched ServicingEntityID"); + assertEquals(createdCast.getServiceTypeRequested(), receivedCast.getServiceTypeRequested(), "mismatched ServiceTypeRequested"); + assertEquals(createdCast.getSupplies(), receivedCast.getSupplies(), "mismatched Supplies"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new ServiceRequestPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/SetDataPduTest.java b/test/edu/nps/moves/dis7/test/SetDataPduTest.java new file mode 100644 index 0000000000..42eec4f1f3 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SetDataPduTest.java @@ -0,0 +1,114 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.FixedDatum; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SetDataPdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.VariableDatum; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; +import edu.nps.moves.dis7.enumerations.VariableRecordType; + +/** + * Unit tests for satisfactory handling of Set Data PDU fields and values. + */ +@DisplayName("SetDataPduTest") +public class SetDataPduTest extends PduTest +{ + /** default constructor */ + public SetDataPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** SetDataPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** SetDataPduTest testMultiplePdus()"); + + SetDataPdu setDataPdu = pduFactory.makeSetDataPdu(); + + setDataPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + setDataPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + setDataPdu.setRequestID(10001); + setDataPdu.getFixedDatums().add(new FixedDatum().setFixedDatumID(VariableRecordType.ENTITY_ID_LIST).setFixedDatumValue(77)); + setDataPdu.getVariableDatums().add(new VariableDatum().setVariableDatumID(VariableRecordType.ENTITY_ID_LIST).setVariableDatumValue(new byte[]{11, 22, 33, 44, 55, 66, 77, 88})); + testOnePdu(setDataPdu); + + setDataPdu.setRequestID(10002); + testOnePdu(setDataPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + SetDataPdu createdCast = (SetDataPdu) createdPdu; + SetDataPdu receivedCast = (SetDataPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getFixedDatums(), receivedCast.getFixedDatums(), "mismatched FixedDatums"); + assertEquals(createdCast.getVariableDatums(), receivedCast.getVariableDatums(), "mismatched VariableDatums"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new SetDataPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/SetDataReliablePduTest.java b/test/edu/nps/moves/dis7/test/SetDataReliablePduTest.java new file mode 100644 index 0000000000..a388e94666 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SetDataReliablePduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SetDataReliablePdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Set Data Reliable PDU fields and values. + */ +@DisplayName("SetDataReliablePduTest") +public class SetDataReliablePduTest extends PduTest +{ + /** default constructor */ + public SetDataReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** SetDataReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** SetDataReliablePduTest testMultiplePdus()"); + + SetDataReliablePdu sdrPdu = pduFactory.makeSetDataReliablePdu(); + + sdrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + sdrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + sdrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + sdrPdu.setRequestID(1001); + testOnePdu(sdrPdu); + + sdrPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + sdrPdu.setRequestID(1002); + testOnePdu(sdrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + SetDataReliablePdu createdCast = (SetDataReliablePdu) createdPdu; + SetDataReliablePdu receivedCast = (SetDataReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getFixedDatumRecords(), receivedCast.getFixedDatumRecords(), "mismatched FixedDatumRecords"); + assertEquals(createdCast.getVariableDatumRecords(), receivedCast.getVariableDatumRecords(), "mismatched VariableDatumRecords"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new SetDataReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/SetRecordReliablePduTest.java b/test/edu/nps/moves/dis7/test/SetRecordReliablePduTest.java new file mode 100644 index 0000000000..532cb9f968 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SetRecordReliablePduTest.java @@ -0,0 +1,112 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SetRecordReliablePdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Set Record Reliable PDU fields and values. + */ +@DisplayName("SetRecordReliablePduTest") +public class SetRecordReliablePduTest extends PduTest +{ + /** default constructor */ + public SetRecordReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** SetRecordReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** SetRecordReliablePduTest testMultiplePdus()"); + + SetRecordReliablePdu srrPdu = pduFactory.makeSetRecordReliablePdu(); + + srrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + srrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + srrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + srrPdu.setRequestID(1201); + testOnePdu(srrPdu); + + srrPdu.setRequiredReliabilityService(RequiredReliabilityService.UNACKNOWLEDGED); + srrPdu.setRequestID(1202); + testOnePdu(srrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + SetRecordReliablePdu createdCast = (SetRecordReliablePdu) createdPdu; + SetRecordReliablePdu receivedCast = (SetRecordReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRecordSets(), receivedCast.getRecordSets(), "mismatched RecordSets"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new SetRecordReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/SimulationAddressTest.java b/test/edu/nps/moves/dis7/test/SimulationAddressTest.java new file mode 100644 index 0000000000..9cbe8577f5 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SimulationAddressTest.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.SimulationAddress; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for SimulationAddress data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("SimulationAddressTest") +public class SimulationAddressTest +{ + private static boolean verbose = true; + + /** default constructor */ + public SimulationAddressTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** SimulationAddressTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** SimulationAddressTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** SimulationAddressTest testDefaultConstructor()"); + + SimulationAddress sa = new SimulationAddress(); + assertEquals(0, sa.getSite(), "mismatched default site"); + assertEquals(0, sa.getApplication(), "mismatched default application"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** SimulationAddressTest testSettersAndGetters()"); + + SimulationAddress sa = new SimulationAddress(); + sa.setSite(42); + sa.setApplication(99); + assertEquals(42, sa.getSite(), "mismatched site"); + assertEquals(99, sa.getApplication(), "mismatched application"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** SimulationAddressTest testMarshalledSize()"); + + SimulationAddress sa = new SimulationAddress(); + assertEquals(4, sa.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** SimulationAddressTest testMarshalUnmarshalDataStream()"); + + SimulationAddress original = new SimulationAddress(); + original.setSite(101); + original.setApplication(202); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + SimulationAddress restored = new SimulationAddress(); + restored.unmarshal(dis); + + assertEquals(original.getSite(), restored.getSite(), "mismatched site after unmarshal"); + assertEquals(original.getApplication(), restored.getApplication(), "mismatched application after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** SimulationAddressTest testMarshalUnmarshalByteBuffer()"); + + SimulationAddress original = new SimulationAddress(); + original.setSite(500); + original.setApplication(600); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + SimulationAddress restored = new SimulationAddress(); + restored.unmarshal(buffer); + + assertEquals(original.getSite(), restored.getSite(), "mismatched site after ByteBuffer unmarshal"); + assertEquals(original.getApplication(), restored.getApplication(), "mismatched application after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** SimulationAddressTest testEquality()"); + + SimulationAddress a = new SimulationAddress(); + a.setSite(1); + a.setApplication(2); + SimulationAddress b = new SimulationAddress(); + b.setSite(1); + b.setApplication(2); + SimulationAddress c = new SimulationAddress(); + c.setSite(1); + c.setApplication(3); + + assertTrue(a.equals(b), "equal SimulationAddresses should be equal"); + assertFalse(a.equals(c), "different SimulationAddresses should not be equal"); + assertEquals(a.hashCode(), b.hashCode(), "equal objects should have equal hashCodes"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("SimulationAddressTest start"); + SimulationAddressTest test = new SimulationAddressTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("SimulationAddressTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/SimulationManagerTest.java b/test/edu/nps/moves/dis7/test/SimulationManagerTest.java new file mode 100644 index 0000000000..3067861289 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/SimulationManagerTest.java @@ -0,0 +1,210 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.utilities.SimulationManager; +import edu.nps.moves.dis7.utilities.SimulationManager.RecordType; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for SimulationManager utility class. + * Tests record management, entity/host tracking, and configuration + * without requiring network access. + */ +@DisplayName("SimulationManagerTest") +public class SimulationManagerTest +{ + private static boolean verbose = true; + + /** helper instance for creating inner RecordType objects */ + private SimulationManager smHelper = new SimulationManager(); + + /** default constructor */ + public SimulationManagerTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** SimulationManagerTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** SimulationManagerTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** SimulationManagerTest testDefaultConstructor()"); + + SimulationManager sm = new SimulationManager(); + assertNotNull(sm, "SimulationManager should not be null"); + } + + @Test + public void testDescriptorConstructor() + { + if (verbose) + System.out.println("*** SimulationManagerTest testDescriptorConstructor()"); + + SimulationManager sm = new SimulationManager("test sim"); + assertEquals("test sim", sm.getDescriptor(), "mismatched descriptor"); + } + + @Test + public void testSetDescriptor() + { + if (verbose) + System.out.println("*** SimulationManagerTest testSetDescriptor()"); + + SimulationManager sm = new SimulationManager(); + sm.setDescriptor("new descriptor"); + assertEquals("new descriptor", sm.getDescriptor(), "mismatched descriptor after set"); + } + + @Test + public void testClearDescriptor() + { + if (verbose) + System.out.println("*** SimulationManagerTest testClearDescriptor()"); + + SimulationManager sm = new SimulationManager("something"); + sm.clearDescriptor(); + assertTrue(sm.getDescriptor().isEmpty(), "descriptor should be empty after clear"); + } + + @Test + public void testRecordType() + { + if (verbose) + System.out.println("*** SimulationManagerTest testRecordType()"); + + RecordType record = smHelper.new RecordType(1, "Entity1", "A test entity", "ref-001"); + assertEquals(1, record.getId(), "mismatched record ID"); + assertEquals("Entity1", record.getName(), "mismatched record name"); + assertEquals("A test entity", record.getDescription(), "mismatched record description"); + assertEquals("ref-001", record.getReference(), "mismatched record reference"); + } + + @Test + public void testRecordTypeSetters() + { + if (verbose) + System.out.println("*** SimulationManagerTest testRecordTypeSetters()"); + + RecordType record = smHelper.new RecordType(1, "Entity1"); + record.setId(2); + record.setName("Entity2"); + record.setDescription("updated description"); + record.setReference("ref-002"); + record.setAlias("alias1"); + + assertEquals(2, record.getId(), "mismatched record ID after set"); + assertEquals("Entity2", record.getName(), "mismatched record name after set"); + assertEquals("updated description", record.getDescription(), "mismatched description after set"); + assertEquals("ref-002", record.getReference(), "mismatched reference after set"); + assertEquals("alias1", record.getAlias(), "mismatched alias after set"); + } + + @Test + public void testEntityListManagement() + { + if (verbose) + System.out.println("*** SimulationManagerTest testEntityListManagement()"); + + SimulationManager sm = new SimulationManager(); + assertNotNull(sm.getEntityRecordList(), "entity list should not be null"); + assertTrue(sm.getEntityRecordList().isEmpty(), "entity list should be empty initially"); + + RecordType entity = smHelper.new RecordType(1, "Tank1"); + sm.addEntity(entity); + assertEquals(1, sm.getEntityRecordList().size(), "entity list should have 1 entry"); + + RecordType retrieved = sm.getEntityRecordByIndex(0); + assertNotNull(retrieved, "retrieved entity should not be null"); + assertEquals("Tank1", retrieved.getName(), "mismatched entity name"); + } + + @Test + public void testHostListManagement() + { + if (verbose) + System.out.println("*** SimulationManagerTest testHostListManagement()"); + + SimulationManager sm = new SimulationManager(); + assertNotNull(sm.getHostRecordList(), "host list should not be null"); + assertTrue(sm.getHostRecordList().isEmpty(), "host list should be empty initially"); + + sm.addHost("localhost"); + assertEquals(1, sm.getHostRecordList().size(), "host list should have 1 entry"); + } + + @Test + public void testClearAll() + { + if (verbose) + System.out.println("*** SimulationManagerTest testClearAll()"); + + SimulationManager sm = new SimulationManager("test"); + sm.addEntity(smHelper.new RecordType(1, "Entity1")); + sm.addHost("host1"); + sm.clearAll(); + + assertTrue(sm.getEntityRecordList().isEmpty(), "entity list should be empty after clearAll"); + assertTrue(sm.getHostRecordList().isEmpty(), "host list should be empty after clearAll"); + } + + @Test + public void testGetPduFactory() + { + if (verbose) + System.out.println("*** SimulationManagerTest testGetPduFactory()"); + + SimulationManager sm = new SimulationManager(); + assertNotNull(sm.getPduFactory(), "PduFactory should not be null"); + } + + @Test + public void testAddEntityById() + { + if (verbose) + System.out.println("*** SimulationManagerTest testAddEntityById()"); + + SimulationManager sm = new SimulationManager(); + EntityID entityId = new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3); + sm.addEntity(entityId); + assertEquals(1, sm.getEntityRecordList().size(), "entity list should have 1 entry after addEntity(EntityID)"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("SimulationManagerTest start"); + SimulationManagerTest test = new SimulationManagerTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testDescriptorConstructor(); + test.testSetDescriptor(); + test.testClearDescriptor(); + test.testRecordType(); + test.testRecordTypeSetters(); + test.testEntityListManagement(); + test.testHostListManagement(); + test.testClearAll(); + test.testGetPduFactory(); + test.testAddEntityById(); + tearDownClass(); + System.out.println("SimulationManagerTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/StartResumePduTest.java b/test/edu/nps/moves/dis7/test/StartResumePduTest.java new file mode 100644 index 0000000000..f9faec4d6f --- /dev/null +++ b/test/edu/nps/moves/dis7/test/StartResumePduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.ClockTime; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.StartResumePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Start/Resume PDU fields and values. + */ +@DisplayName("StartResumePduTest") +public class StartResumePduTest extends PduTest +{ + /** default constructor */ + public StartResumePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** StartResumePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** StartResumePduTest testMultiplePdus()"); + + StartResumePdu startResumePdu = pduFactory.makeStartResumePdu(); + + startResumePdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + startResumePdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + startResumePdu.setRealWorldTime(new ClockTime().setHour(10).setTimePastHour(500000)); + startResumePdu.setSimulationTime(new ClockTime().setHour(0).setTimePastHour(0)); + startResumePdu.setRequestID(3001); + testOnePdu(startResumePdu); + + startResumePdu.setRequestID(3002); + startResumePdu.setRealWorldTime(new ClockTime().setHour(11).setTimePastHour(600000)); + testOnePdu(startResumePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + StartResumePdu createdCast = (StartResumePdu) createdPdu; + StartResumePdu receivedCast = (StartResumePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRealWorldTime(), receivedCast.getRealWorldTime(), "mismatched RealWorldTime"); + assertEquals(createdCast.getSimulationTime(), receivedCast.getSimulationTime(), "mismatched SimulationTime"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new StartResumePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/StartResumeReliablePduTest.java b/test/edu/nps/moves/dis7/test/StartResumeReliablePduTest.java new file mode 100644 index 0000000000..cb1983e4d3 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/StartResumeReliablePduTest.java @@ -0,0 +1,116 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.pdus.ClockTime; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.StartResumeReliablePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Start/Resume Reliable PDU fields and values. + */ +@DisplayName("StartResumeReliablePduTest") +public class StartResumeReliablePduTest extends PduTest +{ + /** default constructor */ + public StartResumeReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** StartResumeReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** StartResumeReliablePduTest testMultiplePdus()"); + + StartResumeReliablePdu srrPdu = pduFactory.makeStartResumeReliablePdu(); + + srrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + srrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + srrPdu.setRealWorldTime(new ClockTime().setHour(10).setTimePastHour(1000000)); + srrPdu.setSimulationTime(new ClockTime().setHour(5).setTimePastHour(500000)); + srrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + srrPdu.setRequestID(301); + testOnePdu(srrPdu); + + srrPdu.setRealWorldTime(new ClockTime().setHour(12).setTimePastHour(2000000)); + srrPdu.setRequestID(302); + testOnePdu(srrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + StartResumeReliablePdu createdCast = (StartResumeReliablePdu) createdPdu; + StartResumeReliablePdu receivedCast = (StartResumeReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRealWorldTime(), receivedCast.getRealWorldTime(), "mismatched RealWorldTime"); + assertEquals(createdCast.getSimulationTime(), receivedCast.getSimulationTime(), "mismatched SimulationTime"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new StartResumeReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/StopFreezePduTest.java b/test/edu/nps/moves/dis7/test/StopFreezePduTest.java new file mode 100644 index 0000000000..c26794d066 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/StopFreezePduTest.java @@ -0,0 +1,115 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.StopFreezeReason; +import edu.nps.moves.dis7.pdus.ClockTime; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.StopFreezePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Stop/Freeze PDU fields and values. + */ +@DisplayName("StopFreezePduTest") +public class StopFreezePduTest extends PduTest +{ + /** default constructor */ + public StopFreezePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** StopFreezePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** StopFreezePduTest testMultiplePdus()"); + + StopFreezePdu stopFreezePdu = pduFactory.makeStopFreezePdu(); + + stopFreezePdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + stopFreezePdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + stopFreezePdu.setRealWorldTime(new ClockTime().setHour(12).setTimePastHour(100000)); + stopFreezePdu.setReason(StopFreezeReason.TERMINATION); + stopFreezePdu.setRequestID(4001); + testOnePdu(stopFreezePdu); + + stopFreezePdu.setRequestID(4002); + stopFreezePdu.setReason(StopFreezeReason.RECESS); + testOnePdu(stopFreezePdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + StopFreezePdu createdCast = (StopFreezePdu) createdPdu; + StopFreezePdu receivedCast = (StopFreezePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRealWorldTime(), receivedCast.getRealWorldTime(), "mismatched RealWorldTime"); + assertEquals(createdCast.getReason(), receivedCast.getReason(), "mismatched Reason"); + assertEquals(createdCast.getFrozenBehavior(), receivedCast.getFrozenBehavior(), "mismatched FrozenBehavior"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new StopFreezePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/StopFreezeReliablePduTest.java b/test/edu/nps/moves/dis7/test/StopFreezeReliablePduTest.java new file mode 100644 index 0000000000..a4a5162045 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/StopFreezeReliablePduTest.java @@ -0,0 +1,120 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.enumerations.StopFreezeFrozenBehavior; +import edu.nps.moves.dis7.enumerations.StopFreezeReason; +import edu.nps.moves.dis7.pdus.ClockTime; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.SimulationIdentifier; +import edu.nps.moves.dis7.pdus.SimulationAddress; +import edu.nps.moves.dis7.pdus.StopFreezeReliablePdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Stop/Freeze Reliable PDU fields and values. + */ +@DisplayName("StopFreezeReliablePduTest") +public class StopFreezeReliablePduTest extends PduTest +{ + /** default constructor */ + public StopFreezeReliablePduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** StopFreezeReliablePduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** StopFreezeReliablePduTest testMultiplePdus()"); + + StopFreezeReliablePdu sfrPdu = pduFactory.makeStopFreezeReliablePdu(); + + sfrPdu.setOriginatingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(1).setApplication(2))); + sfrPdu.setReceivingID(new SimulationIdentifier().setSimulationAddress(new SimulationAddress().setSite(3).setApplication(4))); + sfrPdu.setRealWorldTime(new ClockTime().setHour(10).setTimePastHour(1000000)); + sfrPdu.setReason(StopFreezeReason.TERMINATION); + sfrPdu.setFrozenBehavior(new StopFreezeFrozenBehavior()); + sfrPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + sfrPdu.setRequestID(401); + testOnePdu(sfrPdu); + + sfrPdu.setReason(StopFreezeReason.SECURITY_VIOLATION); + sfrPdu.setRequestID(402); + testOnePdu(sfrPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + StopFreezeReliablePdu createdCast = (StopFreezeReliablePdu) createdPdu; + StopFreezeReliablePdu receivedCast = (StopFreezeReliablePdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingID(), receivedCast.getOriginatingID(), "mismatched OriginatingID"); + assertEquals(createdCast.getReceivingID(), receivedCast.getReceivingID(), "mismatched ReceivingID"); + assertEquals(createdCast.getRealWorldTime(), receivedCast.getRealWorldTime(), "mismatched RealWorldTime"); + assertEquals(createdCast.getReason(), receivedCast.getReason(), "mismatched Reason"); + assertEquals(createdCast.getFrozenBehavior(), receivedCast.getFrozenBehavior(), "mismatched FrozenBehavior"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new StopFreezeReliablePduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/TSPIPduTest.java b/test/edu/nps/moves/dis7/test/TSPIPduTest.java new file mode 100644 index 0000000000..1b03c28880 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/TSPIPduTest.java @@ -0,0 +1,113 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.TSPIPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of TSPI (Time Space Position Information) PDU fields and values. + */ +@DisplayName("TSPIPduTest") +public class TSPIPduTest extends PduTest +{ + /** default constructor */ + public TSPIPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** TSPIPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** TSPIPduTest testMultiplePdus()"); + + TSPIPdu tspiPdu = pduFactory.makeTspiPdu(); + + tspiPdu.setLiveEntityId(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + tspiPdu.setMeasuredSpeed((short) 250); + testOnePdu(tspiPdu); + + tspiPdu.setLiveEntityId(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + tspiPdu.setMeasuredSpeed((short) 500); + testOnePdu(tspiPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + TSPIPdu createdCast = (TSPIPdu) createdPdu; + TSPIPdu receivedCast = (TSPIPdu) receivedPdus.get(0); + + assertEquals(createdCast.getLiveEntityId(), receivedCast.getLiveEntityId(), "mismatched LiveEntityId"); + assertEquals(createdCast.getTSPIFlag(), receivedCast.getTSPIFlag(), "mismatched TSPIFlag"); + assertEquals(createdCast.getEntityLocation(), receivedCast.getEntityLocation(), "mismatched EntityLocation"); + assertEquals(createdCast.getEntityLinearVelocity(), receivedCast.getEntityLinearVelocity(), "mismatched EntityLinearVelocity"); + assertEquals(createdCast.getEntityOrientation(), receivedCast.getEntityOrientation(), "mismatched EntityOrientation"); + assertEquals(createdCast.getPositionError(), receivedCast.getPositionError(), "mismatched PositionError"); + assertEquals(createdCast.getOrientationError(), receivedCast.getOrientationError(), "mismatched OrientationError"); + assertEquals(createdCast.getDeadReckoningParameters(), receivedCast.getDeadReckoningParameters(), "mismatched DeadReckoningParameters"); + assertEquals(createdCast.getMeasuredSpeed(), receivedCast.getMeasuredSpeed(), "mismatched MeasuredSpeed"); + assertArrayEquals(createdCast.getSystemSpecificData(), receivedCast.getSystemSpecificData(), "mismatched SystemSpecificData"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new TSPIPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/TransferOwnershipPduTest.java b/test/edu/nps/moves/dis7/test/TransferOwnershipPduTest.java new file mode 100644 index 0000000000..2ec7da6b24 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/TransferOwnershipPduTest.java @@ -0,0 +1,116 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.RequiredReliabilityService; +import edu.nps.moves.dis7.enumerations.TransferControlTransferType; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.TransferOwnershipPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Transfer Ownership PDU fields and values. + */ +@DisplayName("TransferOwnershipPduTest") +public class TransferOwnershipPduTest extends PduTest +{ + /** default constructor */ + public TransferOwnershipPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** TransferOwnershipPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** TransferOwnershipPduTest testMultiplePdus()"); + + TransferOwnershipPdu toPdu = pduFactory.makeTransferOwnershipPdu(); + + toPdu.setOriginatingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + toPdu.setReceivingEntityID(new EntityID().setSiteID(4).setApplicationID(5).setEntityID(6)); + toPdu.setTransferEntityID(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + toPdu.setRequestID(101); + toPdu.setRequiredReliabilityService(RequiredReliabilityService.ACKNOWLEDGED); + toPdu.setTransferType(TransferControlTransferType.OTHER); + testOnePdu(toPdu); + + toPdu.setRequestID(102); + toPdu.setTransferType(TransferControlTransferType.PUSH_TRANSFER_ENTITY); + testOnePdu(toPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + TransferOwnershipPdu createdCast = (TransferOwnershipPdu) createdPdu; + TransferOwnershipPdu receivedCast = (TransferOwnershipPdu) receivedPdus.get(0); + + assertEquals(createdCast.getOriginatingEntityID(), receivedCast.getOriginatingEntityID(), "mismatched OriginatingEntityID"); + assertEquals(createdCast.getReceivingEntityID(), receivedCast.getReceivingEntityID(), "mismatched ReceivingEntityID"); + assertEquals(createdCast.getRequestID(), receivedCast.getRequestID(), "mismatched RequestID"); + assertEquals(createdCast.getRequiredReliabilityService(), receivedCast.getRequiredReliabilityService(), "mismatched RequiredReliabilityService"); + assertEquals(createdCast.getTransferType(), receivedCast.getTransferType(), "mismatched TransferType"); + assertEquals(createdCast.getTransferEntityID(), receivedCast.getTransferEntityID(), "mismatched TransferEntityID"); + assertEquals(createdCast.getRecordSets(), receivedCast.getRecordSets(), "mismatched RecordSets"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new TransferOwnershipPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/TransmitterPduTest.java b/test/edu/nps/moves/dis7/test/TransmitterPduTest.java new file mode 100644 index 0000000000..1793a5926b --- /dev/null +++ b/test/edu/nps/moves/dis7/test/TransmitterPduTest.java @@ -0,0 +1,122 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.enumerations.TransmitterTransmitState; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.TransmitterPdu; +import edu.nps.moves.dis7.pdus.Vector3Double; +import edu.nps.moves.dis7.pdus.Vector3Float; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Transmitter PDU fields and values. + */ +@DisplayName("TransmitterPduTest") +public class TransmitterPduTest extends PduTest +{ + /** default constructor */ + public TransmitterPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** TransmitterPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** TransmitterPduTest testMultiplePdus()"); + + TransmitterPdu transmitterPdu = pduFactory.makeTransmitterPdu(); + + transmitterPdu.setTransmitState(TransmitterTransmitState.ON_BUT_NOT_TRANSMITTING); + transmitterPdu.setAntennaLocation(new Vector3Double().setX(1000.0).setY(2000.0).setZ(3000.0)); + transmitterPdu.setRelativeAntennaLocation(new Vector3Float().setX(1.0f).setY(2.0f).setZ(3.0f)); + transmitterPdu.setFrequency(300000000L); + transmitterPdu.setTransmitFrequencyBandwidth(10000.0f); + transmitterPdu.setPower(100.0f); + testOnePdu(transmitterPdu); + + transmitterPdu.setTransmitState(TransmitterTransmitState.ON_AND_TRANSMITTING); + transmitterPdu.setFrequency(450000000L); + testOnePdu(transmitterPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + TransmitterPdu createdCast = (TransmitterPdu) createdPdu; + TransmitterPdu receivedCast = (TransmitterPdu) receivedPdus.get(0); + + assertEquals(createdCast.getHeader(), receivedCast.getHeader(), "mismatched Header"); + assertEquals(createdCast.getRadioEntityType(), receivedCast.getRadioEntityType(), "mismatched RadioEntityType"); + assertEquals(createdCast.getTransmitState(), receivedCast.getTransmitState(), "mismatched TransmitState"); + assertEquals(createdCast.getInputSource(), receivedCast.getInputSource(), "mismatched InputSource"); + assertEquals(createdCast.getAntennaLocation(), receivedCast.getAntennaLocation(), "mismatched AntennaLocation"); + assertEquals(createdCast.getRelativeAntennaLocation(), receivedCast.getRelativeAntennaLocation(), "mismatched RelativeAntennaLocation"); + assertEquals(createdCast.getAntennaPatternType(), receivedCast.getAntennaPatternType(), "mismatched AntennaPatternType"); + assertEquals(createdCast.getFrequency(), receivedCast.getFrequency(), "mismatched Frequency"); + assertEquals(createdCast.getTransmitFrequencyBandwidth(), receivedCast.getTransmitFrequencyBandwidth(), "mismatched TransmitFrequencyBandwidth"); + assertEquals(createdCast.getPower(), receivedCast.getPower(), "mismatched Power"); + assertEquals(createdCast.getModulationType(), receivedCast.getModulationType(), "mismatched ModulationType"); + assertEquals(createdCast.getCryptoSystem(), receivedCast.getCryptoSystem(), "mismatched CryptoSystem"); + assertEquals(createdCast.getCryptoKeyId(), receivedCast.getCryptoKeyId(), "mismatched CryptoKeyId"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new TransmitterPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/UnderwaterAcousticPduTest.java b/test/edu/nps/moves/dis7/test/UnderwaterAcousticPduTest.java new file mode 100644 index 0000000000..f1827c2080 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/UnderwaterAcousticPduTest.java @@ -0,0 +1,110 @@ +/* +Copyright (c) 1995-2026 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.UnderwaterAcousticPdu; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for satisfactory handling of Underwater Acoustic PDU fields and values. + */ +@DisplayName("UnderwaterAcousticPduTest") +public class UnderwaterAcousticPduTest extends PduTest +{ + /** default constructor */ + public UnderwaterAcousticPduTest() + { + // initialization code here, but beware order dependencies with JUnit tests + } + + /** preparation **/ + @BeforeAll + public static void setUpClass() + { + if (isVerbose()) + System.out.println("*** UnderwaterAcousticPduTest setUpClass()"); + } + + /** Test PDU sending, receiving, marshalling (serialization) and unmarshalling (deserialization) */ + @Test + @Override + public void testMultiplePdus() + { + if (isVerbose()) + System.out.println("*** UnderwaterAcousticPduTest testMultiplePdus()"); + + UnderwaterAcousticPdu uaPdu = pduFactory.makeUnderwaterAcousticPdu(); + + uaPdu.setEmittingEntityID(new EntityID().setSiteID(1).setApplicationID(2).setEntityID(3)); + uaPdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + testOnePdu(uaPdu); + + uaPdu.setEventID(eventIdentifier.setEventNumber(incrementMasterEventNumber())); + uaPdu.setEmittingEntityID(new EntityID().setSiteID(7).setApplicationID(8).setEntityID(9)); + testOnePdu(uaPdu); + } + + @Override + protected void testOnePdu(Pdu createdPdu) + { + testPduSendReceiveHeaderMatch(createdPdu); + + UnderwaterAcousticPdu createdCast = (UnderwaterAcousticPdu) createdPdu; + UnderwaterAcousticPdu receivedCast = (UnderwaterAcousticPdu) receivedPdus.get(0); + + assertEquals(createdCast.getEmittingEntityID(), receivedCast.getEmittingEntityID(), "mismatched EmittingEntityID"); + assertEquals(createdCast.getEventID(), receivedCast.getEventID(), "mismatched EventID"); + assertEquals(createdCast.getStateChangeIndicator(), receivedCast.getStateChangeIndicator(), "mismatched StateChangeIndicator"); + assertEquals(createdCast.getPassiveParameterIndex(), receivedCast.getPassiveParameterIndex(), "mismatched PassiveParameterIndex"); + assertEquals(createdCast.getShaftRPMs(), receivedCast.getShaftRPMs(), "mismatched ShaftRPMs"); + assertEquals(createdCast.getApaData(), receivedCast.getApaData(), "mismatched ApaData"); + assertEquals(createdCast.getEmitterSystems(), receivedCast.getEmitterSystems(), "mismatched EmitterSystems"); + + testPduCommonFields(createdPdu); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + PduTest test = new UnderwaterAcousticPduTest(); + test.setUp(); + test.testMultiplePdus(); + test.tearDown(); + } +} diff --git a/test/edu/nps/moves/dis7/test/VariableDatumTest.java b/test/edu/nps/moves/dis7/test/VariableDatumTest.java new file mode 100644 index 0000000000..4f42f6750e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/VariableDatumTest.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.VariableDatum; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for VariableDatum data structure. + * Validates construction, variable length handling, and marshal/unmarshal round-trip. + */ +@DisplayName("VariableDatumTest") +public class VariableDatumTest +{ + private static boolean verbose = true; + + /** default constructor */ + public VariableDatumTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** VariableDatumTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** VariableDatumTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** VariableDatumTest testDefaultConstructor()"); + + VariableDatum vd = new VariableDatum(); + assertNotNull(vd.getVariableDatumValue(), "variableDatumValue should not be null"); + } + + @Test + public void testSetVariableDatumValue() + { + if (verbose) + System.out.println("*** VariableDatumTest testSetVariableDatumValue()"); + + VariableDatum vd = new VariableDatum(); + byte[] data = {0x01, 0x02, 0x03, 0x04, 0x05}; + vd.setVariableDatumValue(data); + byte[] result = vd.getVariableDatumValue(); + assertEquals(5, result.length, "mismatched value length"); + assertEquals(0x01, result[0], "mismatched value byte 0"); + assertEquals(0x05, result[4], "mismatched value byte 4"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** VariableDatumTest testMarshalUnmarshalDataStream()"); + + VariableDatum original = new VariableDatum(); + byte[] data = "test data".getBytes(); + original.setVariableDatumValue(data); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + VariableDatum restored = new VariableDatum(); + restored.unmarshal(dis); + + assertArrayEquals(original.getVariableDatumValue(), restored.getVariableDatumValue(), "mismatched variableDatumValue after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** VariableDatumTest testMarshalUnmarshalByteBuffer()"); + + VariableDatum original = new VariableDatum(); + byte[] data = {(byte)0xFF, 0x00, (byte)0xAB, (byte)0xCD}; + original.setVariableDatumValue(data); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + VariableDatum restored = new VariableDatum(); + restored.unmarshal(buffer); + + assertArrayEquals(original.getVariableDatumValue(), restored.getVariableDatumValue(), "mismatched variableDatumValue after ByteBuffer unmarshal"); + } + + @Test + public void testEmptyDatum() throws Exception + { + if (verbose) + System.out.println("*** VariableDatumTest testEmptyDatum()"); + + VariableDatum original = new VariableDatum(); + original.setVariableDatumValue(new byte[0]); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + VariableDatum restored = new VariableDatum(); + restored.unmarshal(dis); + + assertEquals(0, restored.getVariableDatumValue().length, "empty datum should unmarshal to empty value"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("VariableDatumTest start"); + VariableDatumTest test = new VariableDatumTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSetVariableDatumValue(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEmptyDatum(); + tearDownClass(); + System.out.println("VariableDatumTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/Vec3fTest.java b/test/edu/nps/moves/dis7/test/Vec3fTest.java new file mode 100644 index 0000000000..fccf5bede6 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Vec3fTest.java @@ -0,0 +1,290 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.legacy.math.Vec3f; +import edu.nps.moves.legacy.math.Matrix3f; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Vec3f legacy math class. + * Validates vector construction, arithmetic, dot/cross products, normalization, and transforms. + */ +@DisplayName("Vec3fTest") +public class Vec3fTest +{ + private static final float TOLERANCE = 1.0e-5f; + private static boolean verbose = true; + + /** default constructor */ + public Vec3fTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Vec3fTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Vec3fTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Vec3fTest testDefaultConstructor()"); + + Vec3f v = new Vec3f(); + assertEquals(0.0f, v.get(0), TOLERANCE, "mismatched v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "mismatched v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "mismatched v[2]"); + } + + @Test + public void testComponentConstructor() + { + if (verbose) + System.out.println("*** Vec3fTest testComponentConstructor()"); + + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + assertEquals(1.0f, v.get(0), TOLERANCE, "mismatched v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "mismatched v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "mismatched v[2]"); + } + + @Test + public void testCopyConstructor() + { + if (verbose) + System.out.println("*** Vec3fTest testCopyConstructor()"); + + Vec3f original = new Vec3f(4.0f, 5.0f, 6.0f); + Vec3f copy = new Vec3f(original); + assertEquals(original.get(0), copy.get(0), TOLERANCE, "mismatched copy v[0]"); + assertEquals(original.get(1), copy.get(1), TOLERANCE, "mismatched copy v[1]"); + assertEquals(original.get(2), copy.get(2), TOLERANCE, "mismatched copy v[2]"); + } + + @Test + public void testAdd() + { + if (verbose) + System.out.println("*** Vec3fTest testAdd()"); + + Vec3f a = new Vec3f(1.0f, 2.0f, 3.0f); + Vec3f b = new Vec3f(4.0f, 5.0f, 6.0f); + a.add(b); + assertEquals(5.0f, a.get(0), TOLERANCE, "mismatched add v[0]"); + assertEquals(7.0f, a.get(1), TOLERANCE, "mismatched add v[1]"); + assertEquals(9.0f, a.get(2), TOLERANCE, "mismatched add v[2]"); + } + + @Test + public void testAddTwoVectors() + { + if (verbose) + System.out.println("*** Vec3fTest testAddTwoVectors()"); + + Vec3f a = new Vec3f(1.0f, 2.0f, 3.0f); + Vec3f b = new Vec3f(4.0f, 5.0f, 6.0f); + Vec3f result = new Vec3f(); + result.add(a, b); + assertEquals(5.0f, result.get(0), TOLERANCE, "mismatched add v[0]"); + assertEquals(7.0f, result.get(1), TOLERANCE, "mismatched add v[1]"); + assertEquals(9.0f, result.get(2), TOLERANCE, "mismatched add v[2]"); + } + + @Test + public void testSub() + { + if (verbose) + System.out.println("*** Vec3fTest testSub()"); + + Vec3f a = new Vec3f(5.0f, 7.0f, 9.0f); + Vec3f b = new Vec3f(1.0f, 2.0f, 3.0f); + a.sub(b); + assertEquals(4.0f, a.get(0), TOLERANCE, "mismatched sub v[0]"); + assertEquals(5.0f, a.get(1), TOLERANCE, "mismatched sub v[1]"); + assertEquals(6.0f, a.get(2), TOLERANCE, "mismatched sub v[2]"); + } + + @Test + public void testScale() + { + if (verbose) + System.out.println("*** Vec3fTest testScale()"); + + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + v.scale(2.0f); + assertEquals(2.0f, v.get(0), TOLERANCE, "mismatched scale v[0]"); + assertEquals(4.0f, v.get(1), TOLERANCE, "mismatched scale v[1]"); + assertEquals(6.0f, v.get(2), TOLERANCE, "mismatched scale v[2]"); + } + + @Test + public void testNegate() + { + if (verbose) + System.out.println("*** Vec3fTest testNegate()"); + + Vec3f v = new Vec3f(1.0f, -2.0f, 3.0f); + v.negate(); + assertEquals(-1.0f, v.get(0), TOLERANCE, "mismatched negate v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "mismatched negate v[1]"); + assertEquals(-3.0f, v.get(2), TOLERANCE, "mismatched negate v[2]"); + } + + @Test + public void testLength() + { + if (verbose) + System.out.println("*** Vec3fTest testLength()"); + + Vec3f v = new Vec3f(3.0f, 4.0f, 0.0f); + assertEquals(5.0f, v.length(), TOLERANCE, "mismatched length for (3,4,0)"); + + Vec3f unit = new Vec3f(1.0f, 0.0f, 0.0f); + assertEquals(1.0f, unit.length(), TOLERANCE, "mismatched length for unit vector"); + + Vec3f zero = new Vec3f(); + assertEquals(0.0f, zero.length(), TOLERANCE, "mismatched length for zero vector"); + } + + @Test + public void testNormalize() + { + if (verbose) + System.out.println("*** Vec3fTest testNormalize()"); + + Vec3f v = new Vec3f(3.0f, 4.0f, 0.0f); + v.normalize(); + assertEquals(1.0f, v.length(), TOLERANCE, "normalized vector should have unit length"); + assertEquals(0.6f, v.get(0), TOLERANCE, "mismatched normalized v[0]"); + assertEquals(0.8f, v.get(1), TOLERANCE, "mismatched normalized v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "mismatched normalized v[2]"); + } + + @Test + public void testNormalizeZeroVector() + { + if (verbose) + System.out.println("*** Vec3fTest testNormalizeZeroVector()"); + + Vec3f v = new Vec3f(); + v.normalize(); // should not throw, should remain zero + assertEquals(0.0f, v.get(0), TOLERANCE, "zero vector normalize v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "zero vector normalize v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "zero vector normalize v[2]"); + } + + @Test + public void testDotProduct() + { + if (verbose) + System.out.println("*** Vec3fTest testDotProduct()"); + + Vec3f a = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f b = new Vec3f(0.0f, 1.0f, 0.0f); + assertEquals(0.0f, a.dot(b), TOLERANCE, "orthogonal vectors dot product should be 0"); + + Vec3f c = new Vec3f(1.0f, 2.0f, 3.0f); + Vec3f d = new Vec3f(4.0f, 5.0f, 6.0f); + assertEquals(32.0f, c.dot(d), TOLERANCE, "mismatched dot product"); // 1*4 + 2*5 + 3*6 = 32 + + assertEquals(32.0f, Vec3f.dot(c, d), TOLERANCE, "mismatched static dot product"); + } + + @Test + public void testCrossProduct() + { + if (verbose) + System.out.println("*** Vec3fTest testCrossProduct()"); + + // x cross y = z + Vec3f x = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f y = new Vec3f(0.0f, 1.0f, 0.0f); + x.cross(y); + assertEquals(0.0f, x.get(0), TOLERANCE, "mismatched cross v[0]"); + assertEquals(0.0f, x.get(1), TOLERANCE, "mismatched cross v[1]"); + assertEquals(1.0f, x.get(2), TOLERANCE, "mismatched cross v[2]"); + } + + @Test + public void testCrossProductTwoVectors() + { + if (verbose) + System.out.println("*** Vec3fTest testCrossProductTwoVectors()"); + + Vec3f a = new Vec3f(1.0f, 0.0f, 0.0f); + Vec3f b = new Vec3f(0.0f, 1.0f, 0.0f); + Vec3f result = new Vec3f(); + result.cross(a, b); + assertEquals(0.0f, result.get(0), TOLERANCE, "mismatched cross v[0]"); + assertEquals(0.0f, result.get(1), TOLERANCE, "mismatched cross v[1]"); + assertEquals(1.0f, result.get(2), TOLERANCE, "mismatched cross v[2]"); + } + + @Test + public void testMakeNull() + { + if (verbose) + System.out.println("*** Vec3fTest testMakeNull()"); + + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + v.makeNull(); + assertEquals(0.0f, v.get(0), TOLERANCE, "mismatched makeNull v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "mismatched makeNull v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "mismatched makeNull v[2]"); + } + + @Test + public void testXformIdentity() + { + if (verbose) + System.out.println("*** Vec3fTest testXformIdentity()"); + + Vec3f v = new Vec3f(1.0f, 2.0f, 3.0f); + Matrix3f identity = new Matrix3f(); + identity.makeIdent(); + v.xform(identity); + assertEquals(1.0f, v.get(0), TOLERANCE, "identity xform should not change v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "identity xform should not change v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "identity xform should not change v[2]"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("Vec3fTest start"); + Vec3fTest test = new Vec3fTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testComponentConstructor(); + test.testCopyConstructor(); + test.testAdd(); + test.testAddTwoVectors(); + test.testSub(); + test.testScale(); + test.testNegate(); + test.testLength(); + test.testNormalize(); + test.testNormalizeZeroVector(); + test.testDotProduct(); + test.testCrossProduct(); + test.testCrossProductTwoVectors(); + test.testMakeNull(); + test.testXformIdentity(); + tearDownClass(); + System.out.println("Vec3fTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/Vec4fTest.java b/test/edu/nps/moves/dis7/test/Vec4fTest.java new file mode 100644 index 0000000000..dc16c4f405 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Vec4fTest.java @@ -0,0 +1,256 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.legacy.math.Vec4f; +import edu.nps.moves.legacy.math.Matrix4f; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Vec4f legacy math class. + * Validates vector construction, arithmetic, dot product, normalization, and transforms. + */ +@DisplayName("Vec4fTest") +public class Vec4fTest +{ + private static final float TOLERANCE = 1.0e-5f; + private static boolean verbose = true; + + /** default constructor */ + public Vec4fTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Vec4fTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Vec4fTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Vec4fTest testDefaultConstructor()"); + + Vec4f v = new Vec4f(); + assertEquals(0.0f, v.get(0), TOLERANCE, "mismatched v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "mismatched v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "mismatched v[2]"); + assertEquals(0.0f, v.get(3), TOLERANCE, "mismatched v[3]"); + } + + @Test + public void testComponentConstructor() + { + if (verbose) + System.out.println("*** Vec4fTest testComponentConstructor()"); + + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + assertEquals(1.0f, v.get(0), TOLERANCE, "mismatched v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "mismatched v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "mismatched v[2]"); + assertEquals(4.0f, v.get(3), TOLERANCE, "mismatched v[3]"); + } + + @Test + public void testCopyConstructor() + { + if (verbose) + System.out.println("*** Vec4fTest testCopyConstructor()"); + + Vec4f original = new Vec4f(5.0f, 6.0f, 7.0f, 8.0f); + Vec4f copy = new Vec4f(original); + assertEquals(original.get(0), copy.get(0), TOLERANCE, "mismatched copy v[0]"); + assertEquals(original.get(1), copy.get(1), TOLERANCE, "mismatched copy v[1]"); + assertEquals(original.get(2), copy.get(2), TOLERANCE, "mismatched copy v[2]"); + assertEquals(original.get(3), copy.get(3), TOLERANCE, "mismatched copy v[3]"); + } + + @Test + public void testAdd() + { + if (verbose) + System.out.println("*** Vec4fTest testAdd()"); + + Vec4f a = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + Vec4f b = new Vec4f(5.0f, 6.0f, 7.0f, 8.0f); + a.add(b); + assertEquals(6.0f, a.get(0), TOLERANCE, "mismatched add v[0]"); + assertEquals(8.0f, a.get(1), TOLERANCE, "mismatched add v[1]"); + assertEquals(10.0f, a.get(2), TOLERANCE, "mismatched add v[2]"); + assertEquals(12.0f, a.get(3), TOLERANCE, "mismatched add v[3]"); + } + + @Test + public void testSub() + { + if (verbose) + System.out.println("*** Vec4fTest testSub()"); + + Vec4f a = new Vec4f(6.0f, 8.0f, 10.0f, 12.0f); + Vec4f b = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + a.sub(b); + assertEquals(5.0f, a.get(0), TOLERANCE, "mismatched sub v[0]"); + assertEquals(6.0f, a.get(1), TOLERANCE, "mismatched sub v[1]"); + assertEquals(7.0f, a.get(2), TOLERANCE, "mismatched sub v[2]"); + assertEquals(8.0f, a.get(3), TOLERANCE, "mismatched sub v[3]"); + } + + @Test + public void testScale() + { + if (verbose) + System.out.println("*** Vec4fTest testScale()"); + + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + v.scale(3.0f); + assertEquals(3.0f, v.get(0), TOLERANCE, "mismatched scale v[0]"); + assertEquals(6.0f, v.get(1), TOLERANCE, "mismatched scale v[1]"); + assertEquals(9.0f, v.get(2), TOLERANCE, "mismatched scale v[2]"); + assertEquals(12.0f, v.get(3), TOLERANCE, "mismatched scale v[3]"); + } + + @Test + public void testNegate() + { + if (verbose) + System.out.println("*** Vec4fTest testNegate()"); + + Vec4f v = new Vec4f(1.0f, -2.0f, 3.0f, -4.0f); + v.negate(); + assertEquals(-1.0f, v.get(0), TOLERANCE, "mismatched negate v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "mismatched negate v[1]"); + assertEquals(-3.0f, v.get(2), TOLERANCE, "mismatched negate v[2]"); + assertEquals(4.0f, v.get(3), TOLERANCE, "mismatched negate v[3]"); + } + + @Test + public void testLength() + { + if (verbose) + System.out.println("*** Vec4fTest testLength()"); + + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + float expected = (float) Math.sqrt(1 + 4 + 9 + 16); // sqrt(30) + assertEquals(expected, v.length(), TOLERANCE, "mismatched length"); + + Vec4f zero = new Vec4f(); + assertEquals(0.0f, zero.length(), TOLERANCE, "mismatched length for zero vector"); + } + + @Test + public void testNormalize() + { + if (verbose) + System.out.println("*** Vec4fTest testNormalize()"); + + Vec4f v = new Vec4f(2.0f, 0.0f, 0.0f, 0.0f); + v.normalize(); + assertEquals(1.0f, v.length(), TOLERANCE, "normalized vector should have unit length"); + assertEquals(1.0f, v.get(0), TOLERANCE, "mismatched normalized v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "mismatched normalized v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "mismatched normalized v[2]"); + assertEquals(0.0f, v.get(3), TOLERANCE, "mismatched normalized v[3]"); + } + + @Test + public void testNormalizeZeroVector() + { + if (verbose) + System.out.println("*** Vec4fTest testNormalizeZeroVector()"); + + Vec4f v = new Vec4f(); + v.normalize(); // should not throw + assertEquals(0.0f, v.get(0), TOLERANCE, "zero vector normalize v[0]"); + assertEquals(0.0f, v.get(1), TOLERANCE, "zero vector normalize v[1]"); + assertEquals(0.0f, v.get(2), TOLERANCE, "zero vector normalize v[2]"); + assertEquals(0.0f, v.get(3), TOLERANCE, "zero vector normalize v[3]"); + } + + @Test + public void testDotProduct() + { + if (verbose) + System.out.println("*** Vec4fTest testDotProduct()"); + + Vec4f a = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + Vec4f b = new Vec4f(5.0f, 6.0f, 7.0f, 8.0f); + // 1*5 + 2*6 + 3*7 + 4*8 = 5 + 12 + 21 + 32 = 70 + assertEquals(70.0f, a.dot(b), TOLERANCE, "mismatched dot product"); + assertEquals(70.0f, Vec4f.dot(a, b), TOLERANCE, "mismatched static dot product"); + } + + @Test + public void testOrthogonalDot() + { + if (verbose) + System.out.println("*** Vec4fTest testOrthogonalDot()"); + + Vec4f a = new Vec4f(1.0f, 0.0f, 0.0f, 0.0f); + Vec4f b = new Vec4f(0.0f, 1.0f, 0.0f, 0.0f); + assertEquals(0.0f, a.dot(b), TOLERANCE, "orthogonal vectors dot product should be 0"); + } + + @Test + public void testBoundsCheck() + { + if (verbose) + System.out.println("*** Vec4fTest testBoundsCheck()"); + + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + assertEquals(0.0f, v.get(-1), TOLERANCE, "out of bounds get should return 0"); + assertEquals(0.0f, v.get(4), TOLERANCE, "out of bounds get should return 0"); + } + + @Test + public void testXformIdentity() + { + if (verbose) + System.out.println("*** Vec4fTest testXformIdentity()"); + + Vec4f v = new Vec4f(1.0f, 2.0f, 3.0f, 4.0f); + Matrix4f identity = new Matrix4f(); + identity.makeIdent(); + v.xform(identity); + assertEquals(1.0f, v.get(0), TOLERANCE, "identity xform should not change v[0]"); + assertEquals(2.0f, v.get(1), TOLERANCE, "identity xform should not change v[1]"); + assertEquals(3.0f, v.get(2), TOLERANCE, "identity xform should not change v[2]"); + assertEquals(4.0f, v.get(3), TOLERANCE, "identity xform should not change v[3]"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("Vec4fTest start"); + Vec4fTest test = new Vec4fTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testComponentConstructor(); + test.testCopyConstructor(); + test.testAdd(); + test.testSub(); + test.testScale(); + test.testNegate(); + test.testLength(); + test.testNormalize(); + test.testNormalizeZeroVector(); + test.testDotProduct(); + test.testOrthogonalDot(); + test.testBoundsCheck(); + test.testXformIdentity(); + tearDownClass(); + System.out.println("Vec4fTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/Vector3DoubleTest.java b/test/edu/nps/moves/dis7/test/Vector3DoubleTest.java new file mode 100644 index 0000000000..d5ab90e40e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Vector3DoubleTest.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.Vector3Double; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Vector3Double data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("Vector3DoubleTest") +public class Vector3DoubleTest +{ + private static final double TOLERANCE = 1.0e-10; + private static boolean verbose = true; + + /** default constructor */ + public Vector3DoubleTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Vector3DoubleTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Vector3DoubleTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Vector3DoubleTest testDefaultConstructor()"); + + Vector3Double v = new Vector3Double(); + assertEquals(0.0, v.getX(), TOLERANCE, "mismatched default x"); + assertEquals(0.0, v.getY(), TOLERANCE, "mismatched default y"); + assertEquals(0.0, v.getZ(), TOLERANCE, "mismatched default z"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** Vector3DoubleTest testSettersAndGetters()"); + + Vector3Double v = new Vector3Double(); + v.setX(1234567.890123); + v.setY(-9876543.210987); + v.setZ(0.000001); + assertEquals(1234567.890123, v.getX(), TOLERANCE, "mismatched x"); + assertEquals(-9876543.210987, v.getY(), TOLERANCE, "mismatched y"); + assertEquals(0.000001, v.getZ(), TOLERANCE, "mismatched z"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** Vector3DoubleTest testMarshalledSize()"); + + Vector3Double v = new Vector3Double(); + assertEquals(24, v.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** Vector3DoubleTest testMarshalUnmarshalDataStream()"); + + Vector3Double original = new Vector3Double(); + original.setX(-2685587.8486); + original.setY(-4315429.2014); + original.setZ(3836698.4738); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + Vector3Double restored = new Vector3Double(); + restored.unmarshal(dis); + + assertEquals(original.getX(), restored.getX(), TOLERANCE, "mismatched x after unmarshal"); + assertEquals(original.getY(), restored.getY(), TOLERANCE, "mismatched y after unmarshal"); + assertEquals(original.getZ(), restored.getZ(), TOLERANCE, "mismatched z after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** Vector3DoubleTest testMarshalUnmarshalByteBuffer()"); + + Vector3Double original = new Vector3Double(); + original.setX(Double.MAX_VALUE); + original.setY(Double.MIN_VALUE); + original.setZ(-1.0); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + Vector3Double restored = new Vector3Double(); + restored.unmarshal(buffer); + + assertEquals(original.getX(), restored.getX(), TOLERANCE, "mismatched x after ByteBuffer unmarshal"); + assertEquals(original.getY(), restored.getY(), TOLERANCE, "mismatched y after ByteBuffer unmarshal"); + assertEquals(original.getZ(), restored.getZ(), TOLERANCE, "mismatched z after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** Vector3DoubleTest testEquality()"); + + Vector3Double a = new Vector3Double(); + a.setX(1.0); + a.setY(2.0); + a.setZ(3.0); + Vector3Double b = new Vector3Double(); + b.setX(1.0); + b.setY(2.0); + b.setZ(3.0); + Vector3Double c = new Vector3Double(); + c.setX(1.0); + c.setY(2.0); + c.setZ(4.0); + + assertTrue(a.equals(b), "equal Vector3Doubles should be equal"); + assertFalse(a.equals(c), "different Vector3Doubles should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("Vector3DoubleTest start"); + Vector3DoubleTest test = new Vector3DoubleTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("Vector3DoubleTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/Vector3FloatTest.java b/test/edu/nps/moves/dis7/test/Vector3FloatTest.java new file mode 100644 index 0000000000..7beb4057a4 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/Vector3FloatTest.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.Vector3Float; +import java.io.*; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Vector3Float data structure. + * Validates construction, field access, marshal/unmarshal round-trip, and equality. + */ +@DisplayName("Vector3FloatTest") +public class Vector3FloatTest +{ + private static final float TOLERANCE = 1.0e-5f; + private static boolean verbose = true; + + /** default constructor */ + public Vector3FloatTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** Vector3FloatTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** Vector3FloatTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** Vector3FloatTest testDefaultConstructor()"); + + Vector3Float v = new Vector3Float(); + assertEquals(0.0f, v.getX(), TOLERANCE, "mismatched default x"); + assertEquals(0.0f, v.getY(), TOLERANCE, "mismatched default y"); + assertEquals(0.0f, v.getZ(), TOLERANCE, "mismatched default z"); + } + + @Test + public void testSettersAndGetters() + { + if (verbose) + System.out.println("*** Vector3FloatTest testSettersAndGetters()"); + + Vector3Float v = new Vector3Float(); + v.setX(1.5f); + v.setY(2.5f); + v.setZ(3.5f); + assertEquals(1.5f, v.getX(), TOLERANCE, "mismatched x"); + assertEquals(2.5f, v.getY(), TOLERANCE, "mismatched y"); + assertEquals(3.5f, v.getZ(), TOLERANCE, "mismatched z"); + } + + @Test + public void testMarshalledSize() + { + if (verbose) + System.out.println("*** Vector3FloatTest testMarshalledSize()"); + + Vector3Float v = new Vector3Float(); + assertEquals(12, v.getMarshalledSize(), "mismatched marshalled size"); + } + + @Test + public void testMarshalUnmarshalDataStream() throws Exception + { + if (verbose) + System.out.println("*** Vector3FloatTest testMarshalUnmarshalDataStream()"); + + Vector3Float original = new Vector3Float(); + original.setX(10.1f); + original.setY(20.2f); + original.setZ(30.3f); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + original.marshal(dos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + Vector3Float restored = new Vector3Float(); + restored.unmarshal(dis); + + assertEquals(original.getX(), restored.getX(), TOLERANCE, "mismatched x after unmarshal"); + assertEquals(original.getY(), restored.getY(), TOLERANCE, "mismatched y after unmarshal"); + assertEquals(original.getZ(), restored.getZ(), TOLERANCE, "mismatched z after unmarshal"); + } + + @Test + public void testMarshalUnmarshalByteBuffer() throws Exception + { + if (verbose) + System.out.println("*** Vector3FloatTest testMarshalUnmarshalByteBuffer()"); + + Vector3Float original = new Vector3Float(); + original.setX(-5.5f); + original.setY(100.0f); + original.setZ(0.001f); + + ByteBuffer buffer = ByteBuffer.allocate(original.getMarshalledSize()); + original.marshal(buffer); + buffer.flip(); + + Vector3Float restored = new Vector3Float(); + restored.unmarshal(buffer); + + assertEquals(original.getX(), restored.getX(), TOLERANCE, "mismatched x after ByteBuffer unmarshal"); + assertEquals(original.getY(), restored.getY(), TOLERANCE, "mismatched y after ByteBuffer unmarshal"); + assertEquals(original.getZ(), restored.getZ(), TOLERANCE, "mismatched z after ByteBuffer unmarshal"); + } + + @Test + public void testEquality() + { + if (verbose) + System.out.println("*** Vector3FloatTest testEquality()"); + + Vector3Float a = new Vector3Float(); + a.setX(1.0f); + a.setY(2.0f); + a.setZ(3.0f); + Vector3Float b = new Vector3Float(); + b.setX(1.0f); + b.setY(2.0f); + b.setZ(3.0f); + Vector3Float c = new Vector3Float(); + c.setX(1.0f); + c.setY(2.0f); + c.setZ(4.0f); + + assertTrue(a.equals(b), "equal Vector3Floats should be equal"); + assertFalse(a.equals(c), "different Vector3Floats should not be equal"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("Vector3FloatTest start"); + Vector3FloatTest test = new Vector3FloatTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testSettersAndGetters(); + test.testMarshalledSize(); + test.testMarshalUnmarshalDataStream(); + test.testMarshalUnmarshalByteBuffer(); + test.testEquality(); + tearDownClass(); + System.out.println("Vector3FloatTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/X3dCoordinatesTest.java b/test/edu/nps/moves/dis7/test/X3dCoordinatesTest.java new file mode 100644 index 0000000000..3084115906 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/X3dCoordinatesTest.java @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.stream.X3dCoordinates; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for X3dCoordinates data holder class. + * Validates constructors, getters, and setters for coordinate and orientation fields. + */ +@DisplayName("X3dCoordinatesTest") +public class X3dCoordinatesTest +{ + private static boolean verbose = true; + + /** default constructor */ + public X3dCoordinatesTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testDefaultConstructor()"); + + X3dCoordinates coords = new X3dCoordinates(); + assertEquals(0.0, coords.getX(), 1e-9, "mismatched default X"); + assertEquals(0.0, coords.getY(), 1e-9, "mismatched default Y"); + assertEquals(0.0, coords.getZ(), 1e-9, "mismatched default Z"); + assertEquals(0.0, coords.getPhi(), 1e-9, "mismatched default phi"); + assertEquals(0.0, coords.getPsi(), 1e-9, "mismatched default psi"); + assertEquals(0.0, coords.getTheta(), 1e-9, "mismatched default theta"); + } + + @Test + public void testParameterizedConstructor() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testParameterizedConstructor()"); + + X3dCoordinates coords = new X3dCoordinates(1.5, 2.5, 3.5, 0.1, 0.2, 0.3); + assertEquals(1.5, coords.getX(), 1e-9, "mismatched X"); + assertEquals(2.5, coords.getY(), 1e-9, "mismatched Y"); + assertEquals(3.5, coords.getZ(), 1e-9, "mismatched Z"); + assertEquals(0.1, coords.getPhi(), 1e-9, "mismatched phi"); + assertEquals(0.2, coords.getPsi(), 1e-9, "mismatched psi"); + assertEquals(0.3, coords.getTheta(), 1e-9, "mismatched theta"); + } + + @Test + public void testSetX() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetX()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setX(100.0); + assertEquals(100.0, coords.getX(), 1e-9, "mismatched X after set"); + } + + @Test + public void testSetY() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetY()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setY(200.0); + assertEquals(200.0, coords.getY(), 1e-9, "mismatched Y after set"); + } + + @Test + public void testSetZ() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetZ()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setZ(300.0); + assertEquals(300.0, coords.getZ(), 1e-9, "mismatched Z after set"); + } + + @Test + public void testSetPhi() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetPhi()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setPhi(1.5707); + assertEquals(1.5707, coords.getPhi(), 1e-9, "mismatched phi after set"); + } + + @Test + public void testSetPsi() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetPsi()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setPsi(3.1416); + assertEquals(3.1416, coords.getPsi(), 1e-9, "mismatched psi after set"); + } + + @Test + public void testSetTheta() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testSetTheta()"); + + X3dCoordinates coords = new X3dCoordinates(); + coords.setTheta(0.7854); + assertEquals(0.7854, coords.getTheta(), 1e-9, "mismatched theta after set"); + } + + @Test + public void testNegativeCoordinates() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testNegativeCoordinates()"); + + X3dCoordinates coords = new X3dCoordinates(-10.5, -20.5, -30.5, -0.5, -1.0, -1.5); + assertEquals(-10.5, coords.getX(), 1e-9, "mismatched negative X"); + assertEquals(-20.5, coords.getY(), 1e-9, "mismatched negative Y"); + assertEquals(-30.5, coords.getZ(), 1e-9, "mismatched negative Z"); + assertEquals(-0.5, coords.getPhi(), 1e-9, "mismatched negative phi"); + assertEquals(-1.0, coords.getPsi(), 1e-9, "mismatched negative psi"); + assertEquals(-1.5, coords.getTheta(), 1e-9, "mismatched negative theta"); + } + + @Test + public void testLargeCoordinates() + { + if (verbose) + System.out.println("*** X3dCoordinatesTest testLargeCoordinates()"); + + // DIS geocentric coordinates can be very large (Earth radius ~6.4e6 meters) + double earthRadiusX = 4510023.456; + double earthRadiusY = 4510023.456; + double earthRadiusZ = 4367098.123; + X3dCoordinates coords = new X3dCoordinates(earthRadiusX, earthRadiusY, earthRadiusZ, 0.0, 0.0, 0.0); + assertEquals(earthRadiusX, coords.getX(), 1e-9, "mismatched large X"); + assertEquals(earthRadiusY, coords.getY(), 1e-9, "mismatched large Y"); + assertEquals(earthRadiusZ, coords.getZ(), 1e-9, "mismatched large Z"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("X3dCoordinatesTest start"); + X3dCoordinatesTest test = new X3dCoordinatesTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testParameterizedConstructor(); + test.testSetX(); + test.testSetY(); + test.testSetZ(); + test.testSetPhi(); + test.testSetPsi(); + test.testSetTheta(); + test.testNegativeCoordinates(); + test.testLargeCoordinates(); + tearDownClass(); + System.out.println("X3dCoordinatesTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/X3dCreateLineSetTest.java b/test/edu/nps/moves/dis7/test/X3dCreateLineSetTest.java new file mode 100644 index 0000000000..ca8549c789 --- /dev/null +++ b/test/edu/nps/moves/dis7/test/X3dCreateLineSetTest.java @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.pdus.EntityStatePdu; +import edu.nps.moves.dis7.utilities.PduFactory; +import edu.nps.moves.dis7.utilities.stream.X3dCreateLineSet; +import java.nio.ByteBuffer; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for X3dCreateLineSet utility class. + * Validates ESPDU byte buffer processing and point accumulation + * for X3D LineSet generation. + */ +@DisplayName("X3dCreateLineSetTest") +public class X3dCreateLineSetTest +{ + private static boolean verbose = true; + + /** default constructor */ + public X3dCreateLineSetTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest tearDownClass()"); + } + + @Test + public void testDefaultConstructor() + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testDefaultConstructor()"); + + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + assertNotNull(lineSet, "X3dCreateLineSet should not be null"); + } + + @Test + public void testAddPointsWithEspduBytes() throws Exception + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testAddPointsWithEspduBytes()"); + + PduFactory factory = new PduFactory(); + EntityStatePdu espdu = factory.makeEntityStatePdu(); + espdu.getEntityLocation().setX(100.0); + espdu.getEntityLocation().setY(200.0); + espdu.getEntityLocation().setZ(300.0); + + ByteBuffer buffer = espdu.marshal(); + byte[] bytes = new byte[buffer.limit()]; + buffer.rewind(); + buffer.get(bytes); + + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + // addPointsToMap checks byte[2] == 1 for ENTITY_STATE + lineSet.addPointsToMap(bytes); + // no exception means successful processing + } + + @Test + public void testAddMultipleEspduPoints() throws Exception + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testAddMultipleEspduPoints()"); + + PduFactory factory = new PduFactory(); + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + + // add multiple points representing a trajectory + double[][] positions = { + {100.0, 200.0, 300.0}, + {110.0, 210.0, 310.0}, + {120.0, 220.0, 320.0}, + {130.0, 230.0, 330.0} + }; + + for (double[] pos : positions) + { + EntityStatePdu espdu = factory.makeEntityStatePdu(); + espdu.getEntityLocation().setX(pos[0]); + espdu.getEntityLocation().setY(pos[1]); + espdu.getEntityLocation().setZ(pos[2]); + + ByteBuffer buffer = espdu.marshal(); + byte[] bytes = new byte[buffer.limit()]; + buffer.rewind(); + buffer.get(bytes); + + lineSet.addPointsToMap(bytes); + } + // no exception means successful processing of multiple points + } + + @Test + public void testNonEspduBytesIgnored() + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testNonEspduBytesIgnored()"); + + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + + // create a byte array where byte[2] != 1 (not ENTITY_STATE) + byte[] nonEspduBytes = new byte[144]; + nonEspduBytes[2] = 2; // Fire PDU type value + lineSet.addPointsToMap(nonEspduBytes); + // should silently ignore non-ESPDU bytes, no exception + } + + @Test + public void testMakeX3dLineSetEmpty() + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testMakeX3dLineSetEmpty()"); + + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + // calling makeX3dLineSet with no points should not throw + lineSet.makeX3dLineSet(); + } + + @Test + public void testMakeX3dLineSetWithData() throws Exception + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testMakeX3dLineSetWithData()"); + + PduFactory factory = new PduFactory(); + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + + // add enough distinct points to produce a valid LineSet + for (int i = 0; i < 5; i++) + { + EntityStatePdu espdu = factory.makeEntityStatePdu(); + espdu.getEntityLocation().setX(1000.0 + i * 100.0); + espdu.getEntityLocation().setY(2000.0 + i * 50.0); + espdu.getEntityLocation().setZ(3000.0 + i * 25.0); + espdu.setTimestamp(i * 1300000); // use scaled timestamps + + ByteBuffer buffer = espdu.marshal(); + byte[] bytes = new byte[buffer.limit()]; + buffer.rewind(); + buffer.get(bytes); + + lineSet.addPointsToMap(bytes); + } + + // should produce X3D LineSet output to console without exception + lineSet.makeX3dLineSet(); + } + + @Test + public void testInputBufferCloned() throws Exception + { + if (verbose) + System.out.println("*** X3dCreateLineSetTest testInputBufferCloned()"); + + PduFactory factory = new PduFactory(); + EntityStatePdu espdu = factory.makeEntityStatePdu(); + espdu.getEntityLocation().setX(500.0); + espdu.getEntityLocation().setY(600.0); + espdu.getEntityLocation().setZ(700.0); + + ByteBuffer buffer = espdu.marshal(); + byte[] bytes = new byte[buffer.limit()]; + buffer.rewind(); + buffer.get(bytes); + byte[] originalCopy = bytes.clone(); + + X3dCreateLineSet lineSet = new X3dCreateLineSet(); + lineSet.addPointsToMap(bytes); + + // verify input buffer was not modified + assertArrayEquals(originalCopy, bytes, "input buffer should not be modified by addPointsToMap"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) throws Exception + { + System.out.println("X3dCreateLineSetTest start"); + X3dCreateLineSetTest test = new X3dCreateLineSetTest(); + setUpClass(); + test.testDefaultConstructor(); + test.testAddPointsWithEspduBytes(); + test.testAddMultipleEspduPoints(); + test.testNonEspduBytesIgnored(); + test.testMakeX3dLineSetEmpty(); + test.testMakeX3dLineSetWithData(); + test.testInputBufferCloned(); + tearDownClass(); + System.out.println("X3dCreateLineSetTest complete"); + } +} diff --git a/test/edu/nps/moves/dis7/test/X3dSlidingWindowCompressionTest.java b/test/edu/nps/moves/dis7/test/X3dSlidingWindowCompressionTest.java new file mode 100644 index 0000000000..0160f1cc2e --- /dev/null +++ b/test/edu/nps/moves/dis7/test/X3dSlidingWindowCompressionTest.java @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2008-2026, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved. + * This work is provided under a BSD open-source license, see project license.html and license.txt + */ +package edu.nps.moves.dis7.test; + +import edu.nps.moves.dis7.utilities.stream.X3dCoordinates; +import edu.nps.moves.dis7.utilities.stream.X3dSlidingWindowCompression; +import java.util.LinkedHashMap; +import java.util.Map; +import org.junit.jupiter.api.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for X3dSlidingWindowCompression utility class. + * Validates collinear point removal, area threshold behavior, time threshold behavior, + * and edge cases with small input sets. + */ +@DisplayName("X3dSlidingWindowCompressionTest") +public class X3dSlidingWindowCompressionTest +{ + private static boolean verbose = true; + + /** default constructor */ + public X3dSlidingWindowCompressionTest() {} + + @BeforeAll + public static void setUpClass() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest setUpClass()"); + } + + @AfterAll + public static void tearDownClass() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest tearDownClass()"); + } + + @Test + public void testEmptyMap() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testEmptyMap()"); + + Map input = new LinkedHashMap<>(); + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + assertTrue(result.isEmpty(), "result should be empty for empty input"); + } + + @Test + public void testSinglePoint() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testSinglePoint()"); + + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(1.0, 2.0, 3.0, 0.0, 0.0, 0.0)); + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + // single point cannot form a triangle so it stays in the window unprocessed + } + + @Test + public void testTwoPoints() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testTwoPoints()"); + + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(1.0, 1.0, 1.0, 0.0, 0.0, 0.0)); + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + // two points cannot form a triangle so they stay in the window unprocessed + } + + @Test + public void testCollinearPointsRemoved() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testCollinearPointsRemoved()"); + + // Three collinear points on a straight line: (0,0,0) -> (1,1,1) -> (2,2,2) + // Triangle area is zero so the middle point should be removed + // But they need enough time spread (< 4 seconds) to trigger the area-only check + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(1.0, 1.0, 1.0, 0.0, 0.0, 0.0)); + input.put(2.0, new X3dCoordinates(2.0, 2.0, 2.0, 0.0, 0.0, 0.0)); + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + // collinear points within time threshold: all should be kept when stream ends + // (the algorithm keeps all remaining points when streamMap is empty) + assertTrue(result.size() >= 2, "result should retain at least 2 points"); + } + + @Test + public void testNonCollinearPointsRetained() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testNonCollinearPointsRetained()"); + + // Three non-collinear points forming a triangle with area > 0.1 + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(10.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(2.0, new X3dCoordinates(0.0, 10.0, 0.0, 0.0, 0.0, 0.0)); + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + assertTrue(result.size() >= 2, "non-collinear points should be retained"); + } + + @Test + public void testTimeThresholdTriggersOutput() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testTimeThresholdTriggersOutput()"); + + // Points that are collinear but with time span >= 4.0 seconds + // The time threshold should force output even for collinear points + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(1.0, 1.0, 1.0, 0.0, 0.0, 0.0)); + input.put(2.0, new X3dCoordinates(2.0, 2.0, 2.0, 0.0, 0.0, 0.0)); + input.put(5.0, new X3dCoordinates(3.0, 3.0, 3.0, 0.0, 0.0, 0.0)); // time diff >= 4.0 + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + assertTrue(result.size() >= 2, "time threshold should force point output"); + } + + @Test + public void testManyCollinearPoints() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testManyCollinearPoints()"); + + // Many collinear points along the X axis within the time threshold + Map input = new LinkedHashMap<>(); + for (int i = 0; i < 20; i++) + { + input.put((double) i * 0.1, new X3dCoordinates(i * 1.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + } + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + // compression should reduce the number of points + assertTrue(result.size() <= input.size(), "compressed output should not exceed input size"); + assertTrue(result.size() >= 2, "compressed output should have at least 2 points"); + } + + @Test + public void testZigzagPath() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testZigzagPath()"); + + // Zigzag path where every point is non-collinear with large triangle area + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(10.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(2.0, new X3dCoordinates(10.0, 10.0, 0.0, 0.0, 0.0, 0.0)); + input.put(3.0, new X3dCoordinates(20.0, 10.0, 0.0, 0.0, 0.0, 0.0)); + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + // non-collinear zigzag should retain most points + assertTrue(result.size() >= 2, "zigzag path should retain multiple points"); + } + + @Test + public void testPreservesCoordinateValues() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testPreservesCoordinateValues()"); + + // Verify that output coordinate values match input values + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(100.0, 200.0, 300.0, 0.1, 0.2, 0.3)); + input.put(1.0, new X3dCoordinates(110.0, 200.0, 300.0, 0.1, 0.2, 0.3)); + input.put(2.0, new X3dCoordinates(100.0, 210.0, 300.0, 0.1, 0.2, 0.3)); + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + Map result = compressor.doSlidingWindow(); + assertNotNull(result, "result should not be null"); + assertFalse(result.isEmpty(), "result should not be empty"); + + // check that returned coordinates match input values + for (Map.Entry entry : result.entrySet()) + { + X3dCoordinates outputCoord = entry.getValue(); + assertNotNull(outputCoord, "output coordinate should not be null"); + // orientation angles should be preserved + assertEquals(0.1, outputCoord.getPhi(), 1e-9, "mismatched phi in output"); + assertEquals(0.2, outputCoord.getPsi(), 1e-9, "mismatched psi in output"); + assertEquals(0.3, outputCoord.getTheta(), 1e-9, "mismatched theta in output"); + } + } + + @Test + public void testInputMapNotModified() + { + if (verbose) + System.out.println("*** X3dSlidingWindowCompressionTest testInputMapNotModified()"); + + Map input = new LinkedHashMap<>(); + input.put(0.0, new X3dCoordinates(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + input.put(1.0, new X3dCoordinates(1.0, 1.0, 1.0, 0.0, 0.0, 0.0)); + input.put(2.0, new X3dCoordinates(2.0, 2.0, 2.0, 0.0, 0.0, 0.0)); + int originalSize = input.size(); + + X3dSlidingWindowCompression compressor = new X3dSlidingWindowCompression(input); + compressor.doSlidingWindow(); + assertEquals(originalSize, input.size(), "input map should not be modified by compression"); + } + + /** Command-line invocation (CLI) of program, execution starts here + * @param args command-line arguments + */ + public static void main(String[] args) + { + System.out.println("X3dSlidingWindowCompressionTest start"); + X3dSlidingWindowCompressionTest test = new X3dSlidingWindowCompressionTest(); + setUpClass(); + test.testEmptyMap(); + test.testSinglePoint(); + test.testTwoPoints(); + test.testCollinearPointsRemoved(); + test.testNonCollinearPointsRetained(); + test.testTimeThresholdTriggersOutput(); + test.testManyCollinearPoints(); + test.testZigzagPath(); + test.testPreservesCoordinateValues(); + test.testInputMapNotModified(); + tearDownClass(); + System.out.println("X3dSlidingWindowCompressionTest complete"); + } +}