< Summary

Class:ThreatTests
Assembly:bamlab.test.editmode
File(s):/github/workspace/Assets/Tests/EditMode/ThreatTests.cs
Covered lines:0
Uncovered lines:110
Coverable lines:110
Total lines:250
Line coverage:0% (0 of 110)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:9
Method coverage:0% (0 of 9)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Setup()0%2100%
Teardown()0%20400%
Threat_IsNotAssignable()0%2100%
FixedWingThreat_CalculateAccelerationInput_RespectsMaxForwardAcceleration()0%2100%
FixedWingThreat_CalculateAccelerationInput_RespectsMaxNormalAcceleration()0%2100%
RotaryWingThreat_CalculateAccelerationToWaypoint_RespectsMaxForwardAcceleration()0%2100%
RotaryWingThreat_CalculateAccelerationToWaypoint_RespectsMaxNormalAcceleration()0%2100%
RotaryWingThreat_CalculateAccelerationToWaypoint_ComputesCorrectly()0%2100%
AttackBehavior_LoadedCorrectly()0%2100%

File(s)

/github/workspace/Assets/Tests/EditMode/ThreatTests.cs

#LineLine coverage
 1using System;
 2using NUnit.Framework;
 3using UnityEngine;
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.IO;
 7
 8public class ThreatTests : AgentTestBase {
 9  private FixedWingThreat _fixedWingThreat;
 10  private RotaryWingThreat _rotaryWingThreat;
 11
 12  private const string TestDirectAttackPbtxt =
 13      @"
 14      name: ""Test Direct Attack""
 15      type: DIRECT_ATTACK
 16      flight_plan {
 17        type: DISTANCE_TO_TARGET
 18        waypoints {
 19          distance: 10000
 20          altitude: 500
 21          power: MIL
 22        }
 23        waypoints {
 24          distance: 5000
 25          altitude: 100
 26          power: MAX
 27        }
 28      }
 29    ";
 30
 031  public override void Setup() {
 032    base.Setup();
 33    // Write the hard-coded attack behavior to a file.
 034    string attackConfigPath =
 35        ConfigLoader.GetStreamingAssetsFilePath("Configs/Attacks/test_direct_attack.pbtxt");
 036    Directory.CreateDirectory(Path.GetDirectoryName(attackConfigPath));
 037    File.WriteAllText(attackConfigPath, TestDirectAttackPbtxt);
 38
 039    var ucavConfig = new Configs.AgentConfig() {
 40      ConfigFile = "ucav.pbtxt", AttackBehaviorConfigFile = "test_direct_attack.pbtxt",
 41      InitialState =
 42          new Simulation.State() {
 43            Position = new Simulation.CartesianCoordinates() { X = 2000, Y = 100, Z = 4000 },
 44            Velocity = new Simulation.CartesianCoordinates() { X = -50, Y = 0, Z = -100 },
 45          },
 46      StandardDeviation =
 47          new Simulation.State() {
 48            Position = new Simulation.CartesianCoordinates() { X = 400, Y = 300, Z = 400 },
 49            Velocity = new Simulation.CartesianCoordinates() { X = 0, Y = 0, Z = 15 },
 50          },
 51      DynamicConfig =
 52          new Configs.DynamicConfig() {
 53            SensorConfig =
 54                new Simulation.SensorConfig {
 55                  Type = Simulation.SensorType.Ideal,
 56                  Frequency = 100,
 57                },
 58          }
 59    };
 60
 061    var quadcopterConfig = new Configs.AgentConfig() {
 62      ConfigFile = "quadcopter.pbtxt", AttackBehaviorConfigFile = "test_direct_attack.pbtxt",
 63      InitialState =
 64          new Simulation.State() {
 65            Position = new Simulation.CartesianCoordinates() { X = 0, Y = 600, Z = 6000 },
 66            Velocity = new Simulation.CartesianCoordinates() { X = 0, Y = 0, Z = -50 },
 67          },
 68      StandardDeviation =
 69          new Simulation.State() {
 70            Position = new Simulation.CartesianCoordinates() { X = 100, Y = 200, Z = 100 },
 71            Velocity = new Simulation.CartesianCoordinates() { X = 0, Y = 0, Z = 25 },
 72          },
 73      DynamicConfig =
 74          new Configs.DynamicConfig() {
 75            SensorConfig =
 76                new Simulation.SensorConfig {
 77                  Type = Simulation.SensorType.Ideal,
 78                  Frequency = 100,
 79                },
 80          }
 81    };
 82
 083    Agent threatAgent = CreateTestThreat(ucavConfig);
 084    Assert.IsNotNull(threatAgent);
 085    Assert.IsTrue(threatAgent is FixedWingThreat);
 086    _fixedWingThreat = (FixedWingThreat)threatAgent;
 087    Assert.IsNotNull(_fixedWingThreat);
 88
 089    threatAgent = CreateTestThreat(quadcopterConfig);
 090    Assert.IsNotNull(threatAgent);
 091    Assert.IsTrue(threatAgent is RotaryWingThreat);
 092    _rotaryWingThreat = (RotaryWingThreat)threatAgent;
 093    Assert.IsNotNull(_rotaryWingThreat);
 094  }
 95
 096  public override void Teardown() {
 097    base.Teardown();
 98    // Delete the attack configuration file.
 099    string attackConfigPath =
 100        ConfigLoader.GetStreamingAssetsFilePath("Configs/Attacks/test_direct_attack.pbtxt");
 0101    if (File.Exists(attackConfigPath)) {
 0102      File.Delete(attackConfigPath);
 0103    }
 104
 0105    if (_fixedWingThreat != null) {
 0106      GameObject.DestroyImmediate(_fixedWingThreat.gameObject);
 0107    }
 108
 0109    if (_rotaryWingThreat != null) {
 0110      GameObject.DestroyImmediate(_rotaryWingThreat.gameObject);
 0111    }
 0112  }
 113
 114  [Test]
 0115  public void Threat_IsNotAssignable() {
 0116    Assert.IsFalse(_fixedWingThreat.IsAssignable());
 0117    Assert.IsFalse(_rotaryWingThreat.IsAssignable());
 0118  }
 119
 120  [Test]
 0121  public void FixedWingThreat_CalculateAccelerationInput_RespectsMaxForwardAcceleration() {
 0122    SetPrivateField(_fixedWingThreat, "_currentWaypoint", Vector3.one * 1000f);
 0123    Vector3 acceleration =
 124        InvokePrivateMethod<Vector3>(_fixedWingThreat, "CalculateAccelerationInput");
 0125    float maxForwardAcceleration = _fixedWingThreat.CalculateMaxForwardAcceleration();
 126    const float epsilon = 1e-5f;
 0127    Assert.LessOrEqual(Vector3.Project(acceleration, _fixedWingThreat.transform.forward).magnitude,
 128                       maxForwardAcceleration + epsilon);
 0129  }
 130
 131  [Test]
 0132  public void FixedWingThreat_CalculateAccelerationInput_RespectsMaxNormalAcceleration() {
 0133    SetPrivateField(_fixedWingThreat, "_currentWaypoint", Vector3.one * 1000f);
 0134    Vector3 acceleration =
 135        InvokePrivateMethod<Vector3>(_fixedWingThreat, "CalculateAccelerationInput");
 0136    float maxNormalAcceleration = _fixedWingThreat.CalculateMaxNormalAcceleration();
 137    const float epsilon = 1e-5f;
 0138    Assert.LessOrEqual(
 139        acceleration.magnitude, maxNormalAcceleration + epsilon,
 140        $"Acceleration magnitude {acceleration.magnitude} should be less than or equal to the maximum normal acceleratio
 0141  }
 142
 143  [Test]
 0144  public void RotaryWingThreat_CalculateAccelerationToWaypoint_RespectsMaxForwardAcceleration() {
 0145    SetPrivateField(_rotaryWingThreat, "_currentWaypoint", Vector3.one * 1000f);
 0146    Vector3 acceleration =
 147        InvokePrivateMethod<Vector3>(_rotaryWingThreat, "CalculateAccelerationToWaypoint");
 0148    float maxForwardAcceleration = _rotaryWingThreat.CalculateMaxForwardAcceleration();
 149    const float epsilon = 1e-5f;
 0150    Assert.LessOrEqual(Vector3.Project(acceleration, _fixedWingThreat.transform.forward).magnitude,
 151                       maxForwardAcceleration + epsilon);
 0152  }
 153
 154  [Test]
 0155  public void RotaryWingThreat_CalculateAccelerationToWaypoint_RespectsMaxNormalAcceleration() {
 0156    SetPrivateField(_rotaryWingThreat, "_currentWaypoint", Vector3.one * 1000f);
 0157    Vector3 acceleration =
 158        InvokePrivateMethod<Vector3>(_rotaryWingThreat, "CalculateAccelerationToWaypoint");
 0159    float maxNormalAcceleration = _rotaryWingThreat.CalculateMaxNormalAcceleration();
 160    const float epsilon = 1e-5f;
 161    // Calculate the normal acceleration.
 0162    Vector3 forwardComponent = Vector3.Project(acceleration, _rotaryWingThreat.transform.forward);
 0163    Vector3 normalComponent = acceleration - forwardComponent;
 164
 0165    Assert.LessOrEqual(
 166        normalComponent.magnitude, maxNormalAcceleration + epsilon,
 167        $"Normal acceleration magnitude {normalComponent.magnitude} should be less than or equal to the maximum normal a
 0168  }
 169
 170  [Test]
 0171  public void RotaryWingThreat_CalculateAccelerationToWaypoint_ComputesCorrectly() {
 0172    Vector3 initialPosition = new Vector3(0, 0, 0);
 0173    Vector3 waypoint = new Vector3(1000, 0, 0);
 0174    Vector3 initialVelocity = new Vector3(0, 0, 0);
 0175    float desiredSpeed = 50f;
 176
 0177    _rotaryWingThreat.SetPosition(initialPosition);
 0178    SetPrivateField(_rotaryWingThreat, "_currentWaypoint", waypoint);
 0179    _rotaryWingThreat.SetVelocity(initialVelocity);
 0180    SetPrivateField(_rotaryWingThreat, "_currentPower", Configs.Power.Mil);
 181
 182    // Assume that the lookup power table returns 50 for MIL.
 0183    float power =
 184        InvokePrivateMethod<float>(_rotaryWingThreat, "LookupPowerTable", Configs.Power.Mil);
 0185    Assert.AreEqual(desiredSpeed, power);
 186
 0187    Vector3 accelerationInput =
 188        InvokePrivateMethod<Vector3>(_rotaryWingThreat, "CalculateAccelerationToWaypoint");
 189
 0190    Vector3 toWaypoint = waypoint - initialPosition;
 0191    Vector3 expectedAccelerationDir = toWaypoint.normalized;
 0192    float expectedAccelerationMag = desiredSpeed / (float)Time.fixedDeltaTime;
 0193    Vector3 expectedAcceleration = expectedAccelerationDir * expectedAccelerationMag;
 194
 195    // Decompose acceleration into forward and normal components.
 0196    Vector3 forwardAcceleration =
 197        Vector3.Project(expectedAcceleration, _rotaryWingThreat.transform.forward);
 0198    Vector3 normalAcceleration = expectedAcceleration - forwardAcceleration;
 199
 200    // Limit the acceleration magnitude.
 0201    float maxForwardAcceleration = _rotaryWingThreat.CalculateMaxNormalAcceleration();
 0202    forwardAcceleration = Vector3.ClampMagnitude(forwardAcceleration, maxForwardAcceleration);
 0203    float maxNormalAcceleration = _rotaryWingThreat.CalculateMaxNormalAcceleration();
 0204    normalAcceleration = Vector3.ClampMagnitude(normalAcceleration, maxNormalAcceleration);
 0205    expectedAcceleration = forwardAcceleration + normalAcceleration;
 206
 0207    Assert.AreEqual(expectedAcceleration.magnitude, accelerationInput.magnitude, 0.1f,
 208                    "Acceleration magnitude should match expected.");
 0209    Assert.AreEqual(expectedAcceleration.normalized, accelerationInput.normalized,
 210                    "Acceleration direction should be towards waypoint.");
 0211  }
 212
 213  [Test]
 0214  public void AttackBehavior_LoadedCorrectly() {
 0215    try {
 0216      AttackBehavior attackBehavior =
 217          GetPrivateField<AttackBehavior>(_fixedWingThreat, "_attackBehavior");
 0218      Assert.IsNotNull(attackBehavior, "Attack behavior should not be null.");
 0219      Assert.AreEqual("Test Direct Attack", attackBehavior.Name);
 0220      Assert.AreEqual(Configs.AttackType.DirectAttack, attackBehavior.Type);
 221
 0222      Assert.IsTrue(attackBehavior is DirectAttackBehavior,
 223                    "Attack behavior should be a DirectAttackBehavior.");
 0224      DirectAttackBehavior directAttackBehavior = (DirectAttackBehavior)attackBehavior;
 225
 0226      Assert.IsNotNull(attackBehavior.FlightPlan, "Flight plan should not be null.");
 0227      Assert.AreEqual(Configs.AttackBehaviorConfig.Types.FlightPlanType.DistanceToTarget,
 228                      attackBehavior.FlightPlan.Type);
 229
 0230      List<Waypoint> waypoints = attackBehavior.FlightPlan.Waypoints;
 0231      Assert.IsNotNull(waypoints, "Waypoints should not be null.");
 0232      Assert.AreEqual(2, waypoints.Count, "There should be 2 waypoints.");
 233
 0234      Assert.AreEqual(10000f, waypoints[0].Distance);
 0235      Assert.AreEqual(500f, waypoints[0].Altitude);
 0236      Assert.AreEqual(Configs.Power.Mil, waypoints[0].Power);
 237
 0238      Assert.AreEqual(5000f, waypoints[1].Distance);
 0239      Assert.AreEqual(100f, waypoints[1].Altitude);
 0240      Assert.AreEqual(Configs.Power.Max, waypoints[1].Power);
 241
 0242      GameObject.DestroyImmediate(_simManager.gameObject);
 0243    } catch (AssertionException e) {
 0244      throw new AssertionException(
 245          e.Message + "\n" + "This test likely failed because you have edited " +
 246          "the test string at the top of the test. Please update the test with the new values.\n" +
 247          "If you need to change the test values, please update the test string at the top of the test.");
 248    }
 0249  }
 250}