%PDF- %PDF-
Direktori : /lib/python3/dist-packages/twisted/positioning/test/ |
Current File : //lib/python3/dist-packages/twisted/positioning/test/test_base.py |
# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ Test cases for positioning primitives. """ from __future__ import annotations from zope.interface import verify from twisted.positioning import base from twisted.positioning.base import Angles, Directions from twisted.positioning.ipositioning import IPositioningBeacon from twisted.trial.unittest import TestCase class AngleTests(TestCase): """ Tests for the L{twisted.positioning.base.Angle} class. """ def test_empty(self) -> None: """ The repr of an empty angle says that is of unknown type and unknown value. """ a = base.Angle() self.assertEqual("<Angle of unknown type (unknown value)>", repr(a)) def test_variation(self) -> None: """ The repr of an empty variation says that it is a variation of unknown value. """ a = base.Angle(angleType=Angles.VARIATION) self.assertEqual("<Variation (unknown value)>", repr(a)) def test_unknownType(self) -> None: """ The repr of an angle of unknown type but a given value displays that type and value in its repr. """ a = base.Angle(1.0) self.assertEqual("<Angle of unknown type (1.0 degrees)>", repr(a)) def test_bogusType(self) -> None: """ Trying to create an angle with a bogus type raises C{ValueError}. """ self.assertRaises(ValueError, base.Angle, angleType="BOGUS") class HeadingTests(TestCase): """ Tests for the L{twisted.positioning.base.Heading} class. """ def test_simple(self) -> None: """ Tests that a simple heading has a value in decimal degrees, which is also its value when converted to a float. Its variation, and by consequence its corrected heading, is L{None}. """ h = base.Heading(1.0) self.assertEqual(h.inDecimalDegrees, 1.0) self.assertEqual(float(h), 1.0) self.assertIsNone(h.variation) self.assertIsNone(h.correctedHeading) def test_headingWithoutVariationRepr(self) -> None: """ A repr of a heading with no variation reports its value and that the variation is unknown. """ heading = base.Heading(1.0) expectedRepr = "<Heading (1.0 degrees, unknown variation)>" self.assertEqual(repr(heading), expectedRepr) def test_headingWithVariationRepr(self) -> None: """ A repr of a heading with known variation reports its value and the value of that variation. """ angle, variation = 1.0, -10.0 heading = base.Heading.fromFloats(angle, variationValue=variation) reprTemplate = "<Heading ({0} degrees, <Variation ({1} degrees)>)>" self.assertEqual(repr(heading), reprTemplate.format(angle, variation)) def test_valueEquality(self) -> None: """ Headings with the same values compare equal. """ self.assertEqual(base.Heading(1.0), base.Heading(1.0)) def test_valueInequality(self) -> None: """ Headings with different values compare unequal. """ self.assertNotEqual(base.Heading(1.0), base.Heading(2.0)) def test_zeroHeadingEdgeCase(self) -> None: """ Headings can be instantiated with a value of 0 and no variation. """ base.Heading(0) def test_zeroHeading180DegreeVariationEdgeCase(self) -> None: """ Headings can be instantiated with a value of 0 and a variation of 180 degrees. """ base.Heading(0, 180) def _badValueTest(self, **kw: float) -> None: """ Helper function for verifying that bad values raise C{ValueError}. @param kw: The keyword arguments passed to L{base.Heading.fromFloats}. """ self.assertRaises(ValueError, base.Heading.fromFloats, **kw) def test_badAngleValueEdgeCase(self) -> None: """ Headings can not be instantiated with a value of 360 degrees. """ self._badValueTest(angleValue=360.0) def test_badVariationEdgeCase(self) -> None: """ Headings can not be instantiated with a variation of -180 degrees. """ self._badValueTest(variationValue=-180.0) def test_negativeHeading(self) -> None: """ Negative heading values raise C{ValueError}. """ self._badValueTest(angleValue=-10.0) def test_headingTooLarge(self) -> None: """ Heading values greater than C{360.0} raise C{ValueError}. """ self._badValueTest(angleValue=370.0) def test_variationTooNegative(self) -> None: """ Variation values less than C{-180.0} raise C{ValueError}. """ self._badValueTest(variationValue=-190.0) def test_variationTooPositive(self) -> None: """ Variation values greater than C{180.0} raise C{ValueError}. """ self._badValueTest(variationValue=190.0) def test_correctedHeading(self) -> None: """ A heading with a value and a variation has a corrected heading. """ h = base.Heading.fromFloats(1.0, variationValue=-10.0) self.assertEqual(h.correctedHeading, base.Angle(11.0, Angles.HEADING)) def test_correctedHeadingOverflow(self) -> None: """ A heading with a value and a variation has the appropriate corrected heading value, even when the variation puts it across the 360 degree boundary. """ h = base.Heading.fromFloats(359.0, variationValue=-2.0) self.assertEqual(h.correctedHeading, base.Angle(1.0, Angles.HEADING)) def test_correctedHeadingOverflowEdgeCase(self) -> None: """ A heading with a value and a variation has the appropriate corrected heading value, even when the variation puts it exactly at the 360 degree boundary. """ h = base.Heading.fromFloats(359.0, variationValue=-1.0) self.assertEqual(h.correctedHeading, base.Angle(0.0, Angles.HEADING)) def test_correctedHeadingUnderflow(self) -> None: """ A heading with a value and a variation has the appropriate corrected heading value, even when the variation puts it under the 0 degree boundary. """ h = base.Heading.fromFloats(1.0, variationValue=2.0) self.assertEqual(h.correctedHeading, base.Angle(359.0, Angles.HEADING)) def test_correctedHeadingUnderflowEdgeCase(self) -> None: """ A heading with a value and a variation has the appropriate corrected heading value, even when the variation puts it exactly at the 0 degree boundary. """ h = base.Heading.fromFloats(1.0, variationValue=1.0) self.assertEqual(h.correctedHeading, base.Angle(0.0, Angles.HEADING)) def test_setVariationSign(self) -> None: """ Setting the sign of a heading changes the variation sign. """ h = base.Heading.fromFloats(1.0, variationValue=1.0) h.setSign(1) self.assertEqual(h.variation.inDecimalDegrees, 1.0) h.setSign(-1) self.assertEqual(h.variation.inDecimalDegrees, -1.0) def test_setBadVariationSign(self) -> None: """ Setting the sign of a heading to values that aren't C{-1} or C{1} raises C{ValueError} and does not affect the heading. """ h = base.Heading.fromFloats(1.0, variationValue=1.0) self.assertRaises(ValueError, h.setSign, -50) self.assertEqual(h.variation.inDecimalDegrees, 1.0) self.assertRaises(ValueError, h.setSign, 0) self.assertEqual(h.variation.inDecimalDegrees, 1.0) self.assertRaises(ValueError, h.setSign, 50) self.assertEqual(h.variation.inDecimalDegrees, 1.0) def test_setUnknownVariationSign(self) -> None: """ Setting the sign on a heading with unknown variation raises C{ValueError}. """ h = base.Heading.fromFloats(1.0) self.assertIsNone(h.variation.inDecimalDegrees) self.assertRaises(ValueError, h.setSign, 1) class CoordinateTests(TestCase): def test_float(self) -> None: """ Coordinates can be converted to floats. """ coordinate = base.Coordinate(10.0) self.assertEqual(float(coordinate), 10.0) def test_repr(self) -> None: """ Coordinates that aren't explicitly latitudes or longitudes have an appropriate repr. """ coordinate = base.Coordinate(10.0) expectedRepr = f"<Angle of unknown type ({10.0} degrees)>" self.assertEqual(repr(coordinate), expectedRepr) def test_positiveLatitude(self) -> None: """ Positive latitudes have a repr that specifies their type and value. """ coordinate = base.Coordinate(10.0, Angles.LATITUDE) expectedRepr = f"<Latitude ({10.0} degrees)>" self.assertEqual(repr(coordinate), expectedRepr) def test_negativeLatitude(self) -> None: """ Negative latitudes have a repr that specifies their type and value. """ coordinate = base.Coordinate(-50.0, Angles.LATITUDE) expectedRepr = f"<Latitude ({-50.0} degrees)>" self.assertEqual(repr(coordinate), expectedRepr) def test_positiveLongitude(self) -> None: """ Positive longitudes have a repr that specifies their type and value. """ longitude = base.Coordinate(50.0, Angles.LONGITUDE) expectedRepr = f"<Longitude ({50.0} degrees)>" self.assertEqual(repr(longitude), expectedRepr) def test_negativeLongitude(self) -> None: """ Negative longitudes have a repr that specifies their type and value. """ longitude = base.Coordinate(-50.0, Angles.LONGITUDE) expectedRepr = f"<Longitude ({-50.0} degrees)>" self.assertEqual(repr(longitude), expectedRepr) def test_bogusCoordinateType(self) -> None: """ Creating coordinates with bogus types rasies C{ValueError}. """ self.assertRaises(ValueError, base.Coordinate, 150.0, "BOGUS") def test_angleTypeNotCoordinate(self) -> None: """ Creating coordinates with angle types that aren't coordinates raises C{ValueError}. """ self.assertRaises(ValueError, base.Coordinate, 150.0, Angles.HEADING) def test_equality(self) -> None: """ Coordinates with the same value and type are equal. """ def makeCoordinate() -> base.Coordinate: return base.Coordinate(1.0, Angles.LONGITUDE) self.assertEqual(makeCoordinate(), makeCoordinate()) def test_differentAnglesInequality(self) -> None: """ Coordinates with different values aren't equal. """ c1 = base.Coordinate(1.0) c2 = base.Coordinate(-1.0) self.assertNotEqual(c1, c2) def test_differentTypesInequality(self) -> None: """ Coordinates with the same values but different types aren't equal. """ c1 = base.Coordinate(1.0, Angles.LATITUDE) c2 = base.Coordinate(1.0, Angles.LONGITUDE) self.assertNotEqual(c1, c2) def test_sign(self) -> None: """ Setting the sign on a coordinate sets the sign of the value of the coordinate. """ c = base.Coordinate(50.0, Angles.LATITUDE) c.setSign(1) self.assertEqual(c.inDecimalDegrees, 50.0) c.setSign(-1) self.assertEqual(c.inDecimalDegrees, -50.0) def test_badVariationSign(self) -> None: """ Setting a bogus sign value (not -1 or 1) on a coordinate raises C{ValueError} and doesn't affect the coordinate. """ value = 50.0 c = base.Coordinate(value, Angles.LATITUDE) self.assertRaises(ValueError, c.setSign, -50) self.assertEqual(c.inDecimalDegrees, 50.0) self.assertRaises(ValueError, c.setSign, 0) self.assertEqual(c.inDecimalDegrees, 50.0) self.assertRaises(ValueError, c.setSign, 50) self.assertEqual(c.inDecimalDegrees, 50.0) def test_northernHemisphere(self) -> None: """ Positive latitudes are in the northern hemisphere. """ coordinate = base.Coordinate(1.0, Angles.LATITUDE) self.assertEqual(coordinate.hemisphere, Directions.NORTH) def test_easternHemisphere(self) -> None: """ Positive longitudes are in the eastern hemisphere. """ coordinate = base.Coordinate(1.0, Angles.LONGITUDE) self.assertEqual(coordinate.hemisphere, Directions.EAST) def test_southernHemisphere(self) -> None: """ Negative latitudes are in the southern hemisphere. """ coordinate = base.Coordinate(-1.0, Angles.LATITUDE) self.assertEqual(coordinate.hemisphere, Directions.SOUTH) def test_westernHemisphere(self) -> None: """ Negative longitudes are in the western hemisphere. """ coordinate = base.Coordinate(-1.0, Angles.LONGITUDE) self.assertEqual(coordinate.hemisphere, Directions.WEST) def test_badHemisphere(self) -> None: """ Accessing the hemisphere for a coordinate that can't compute it raises C{ValueError}. """ coordinate = base.Coordinate(1.0, None) self.assertRaises(ValueError, lambda: coordinate.hemisphere) def test_latitudeTooLarge(self) -> None: """ Creating a latitude with a value greater than or equal to 90 degrees raises C{ValueError}. """ self.assertRaises(ValueError, _makeLatitude, 150.0) self.assertRaises(ValueError, _makeLatitude, 90.0) def test_latitudeTooSmall(self) -> None: """ Creating a latitude with a value less than or equal to -90 degrees raises C{ValueError}. """ self.assertRaises(ValueError, _makeLatitude, -150.0) self.assertRaises(ValueError, _makeLatitude, -90.0) def test_longitudeTooLarge(self) -> None: """ Creating a longitude with a value greater than or equal to 180 degrees raises C{ValueError}. """ self.assertRaises(ValueError, _makeLongitude, 250.0) self.assertRaises(ValueError, _makeLongitude, 180.0) def test_longitudeTooSmall(self) -> None: """ Creating a longitude with a value less than or equal to -180 degrees raises C{ValueError}. """ self.assertRaises(ValueError, _makeLongitude, -250.0) self.assertRaises(ValueError, _makeLongitude, -180.0) def test_inDegreesMinutesSeconds(self) -> None: """ Coordinate values can be accessed in degrees, minutes, seconds. """ c = base.Coordinate(50.5, Angles.LATITUDE) self.assertEqual(c.inDegreesMinutesSeconds, (50, 30, 0)) c = base.Coordinate(50.213, Angles.LATITUDE) self.assertEqual(c.inDegreesMinutesSeconds, (50, 12, 46)) def test_unknownAngleInDegreesMinutesSeconds(self) -> None: """ If the vaue of a coordinate is L{None}, its values in degrees, minutes, seconds is also L{None}. """ c = base.Coordinate(None, None) self.assertIsNone(c.inDegreesMinutesSeconds) def _makeLatitude(value: float) -> base.Coordinate: """ Builds and returns a latitude of given value. """ return base.Coordinate(value, Angles.LATITUDE) def _makeLongitude(value: float) -> base.Coordinate: """ Builds and returns a longitude of given value. """ return base.Coordinate(value, Angles.LONGITUDE) class AltitudeTests(TestCase): """ Tests for the L{twisted.positioning.base.Altitude} class. """ def test_value(self) -> None: """ Altitudes can be instantiated and reports the correct value in meters and feet, as well as when converted to float. """ altitude = base.Altitude(1.0) self.assertEqual(float(altitude), 1.0) self.assertEqual(altitude.inMeters, 1.0) self.assertEqual(altitude.inFeet, 1.0 / base.METERS_PER_FOOT) def test_repr(self) -> None: """ Altitudes report their type and value in their repr. """ altitude = base.Altitude(1.0) self.assertEqual(repr(altitude), "<Altitude (1.0 m)>") def test_equality(self) -> None: """ Altitudes with equal values compare equal. """ firstAltitude = base.Altitude(1.0) secondAltitude = base.Altitude(1.0) self.assertEqual(firstAltitude, secondAltitude) def test_inequality(self) -> None: """ Altitudes with different values don't compare equal. """ firstAltitude = base.Altitude(1.0) secondAltitude = base.Altitude(-1.0) self.assertNotEqual(firstAltitude, secondAltitude) class SpeedTests(TestCase): """ Tests for the L{twisted.positioning.base.Speed} class. """ def test_value(self) -> None: """ Speeds can be instantiated, and report their value in meters per second, and can be converted to floats. """ speed = base.Speed(50.0) self.assertEqual(speed.inMetersPerSecond, 50.0) self.assertEqual(float(speed), 50.0) def test_repr(self) -> None: """ Speeds report their type and value in their repr. """ speed = base.Speed(50.0) self.assertEqual(repr(speed), "<Speed (50.0 m/s)>") def test_negativeSpeeds(self) -> None: """ Creating a negative speed raises C{ValueError}. """ self.assertRaises(ValueError, base.Speed, -1.0) def test_inKnots(self) -> None: """ A speed can be converted into its value in knots. """ speed = base.Speed(1.0) self.assertEqual(1 / base.MPS_PER_KNOT, speed.inKnots) def test_asFloat(self) -> None: """ A speed can be converted into a C{float}. """ self.assertEqual(1.0, float(base.Speed(1.0))) class ClimbTests(TestCase): """ Tests for L{twisted.positioning.base.Climb}. """ def test_simple(self) -> None: """ Speeds can be instantiated, and report their value in meters per second, and can be converted to floats. """ climb = base.Climb(42.0) self.assertEqual(climb.inMetersPerSecond, 42.0) self.assertEqual(float(climb), 42.0) def test_repr(self) -> None: """ Climbs report their type and value in their repr. """ climb = base.Climb(42.0) self.assertEqual(repr(climb), "<Climb (42.0 m/s)>") def test_negativeClimbs(self) -> None: """ Climbs can have negative values, and still report that value in meters per second and when converted to floats. """ climb = base.Climb(-42.0) self.assertEqual(climb.inMetersPerSecond, -42.0) self.assertEqual(float(climb), -42.0) def test_speedInKnots(self) -> None: """ A climb can be converted into its value in knots. """ climb = base.Climb(1.0) self.assertEqual(1 / base.MPS_PER_KNOT, climb.inKnots) def test_asFloat(self) -> None: """ A climb can be converted into a C{float}. """ self.assertEqual(1.0, float(base.Climb(1.0))) class PositionErrorTests(TestCase): """ Tests for L{twisted.positioning.base.PositionError}. """ def test_allUnset(self) -> None: """ In an empty L{base.PositionError} with no invariant testing, all dilutions of positions are L{None}. """ positionError = base.PositionError() self.assertIsNone(positionError.pdop) self.assertIsNone(positionError.hdop) self.assertIsNone(positionError.vdop) def test_allUnsetWithInvariant(self) -> None: """ In an empty L{base.PositionError} with invariant testing, all dilutions of positions are L{None}. """ positionError = base.PositionError(testInvariant=True) self.assertIsNone(positionError.pdop) self.assertIsNone(positionError.hdop) self.assertIsNone(positionError.vdop) def test_withoutInvariant(self) -> None: """ L{base.PositionError}s can be instantiated with just a HDOP. """ positionError = base.PositionError(hdop=1.0) self.assertEqual(positionError.hdop, 1.0) def test_withInvariant(self) -> None: """ Creating a simple L{base.PositionError} with just a HDOP while checking the invariant works. """ positionError = base.PositionError(hdop=1.0, testInvariant=True) self.assertEqual(positionError.hdop, 1.0) def test_invalidWithoutInvariant(self) -> None: """ Creating a L{base.PositionError} with values set to an impossible combination works if the invariant is not checked. """ error = base.PositionError(pdop=1.0, vdop=1.0, hdop=1.0) self.assertEqual(error.pdop, 1.0) self.assertEqual(error.hdop, 1.0) self.assertEqual(error.vdop, 1.0) def test_invalidWithInvariant(self) -> None: """ Creating a L{base.PositionError} with values set to an impossible combination raises C{ValueError} if the invariant is being tested. """ self.assertRaises( ValueError, base.PositionError, pdop=1.0, vdop=1.0, hdop=1.0, testInvariant=True, ) def test_setDOPWithoutInvariant(self) -> None: """ You can set the PDOP value to value inconsisted with HDOP and VDOP when not checking the invariant. """ pe = base.PositionError(hdop=1.0, vdop=1.0) pe.pdop = 100.0 self.assertEqual(pe.pdop, 100.0) def test_setDOPWithInvariant(self) -> None: """ Attempting to set the PDOP value to value inconsisted with HDOP and VDOP when checking the invariant raises C{ValueError}. """ pe = base.PositionError(hdop=1.0, vdop=1.0, testInvariant=True) pdop = pe.pdop def setPDOP(pe: base.PositionError) -> None: pe.pdop = 100.0 self.assertRaises(ValueError, setPDOP, pe) self.assertEqual(pe.pdop, pdop) REPR_TEMPLATE = "<PositionError (pdop: %s, hdop: %s, vdop: %s)>" def _testDOP( self, pe: base.PositionError, pdop: float | None, hdop: float | None, vdop: float | None, ) -> None: """ Tests the DOP values in a position error, and the repr of that position error. @param pe: The position error under test. @type pe: C{PositionError} @param pdop: The expected position dilution of precision. @type pdop: C{float} or L{None} @param hdop: The expected horizontal dilution of precision. @type hdop: C{float} or L{None} @param vdop: The expected vertical dilution of precision. @type vdop: C{float} or L{None} """ self.assertEqual(pe.pdop, pdop) self.assertEqual(pe.hdop, hdop) self.assertEqual(pe.vdop, vdop) self.assertEqual(repr(pe), self.REPR_TEMPLATE % (pdop, hdop, vdop)) def test_positionAndHorizontalSet(self) -> None: """ The VDOP is correctly determined from PDOP and HDOP. """ pdop, hdop = 2.0, 1.0 vdop = (pdop**2 - hdop**2) ** 0.5 pe = base.PositionError(pdop=pdop, hdop=hdop) self._testDOP(pe, pdop, hdop, vdop) def test_positionAndVerticalSet(self) -> None: """ The HDOP is correctly determined from PDOP and VDOP. """ pdop, vdop = 2.0, 1.0 hdop = (pdop**2 - vdop**2) ** 0.5 pe = base.PositionError(pdop=pdop, vdop=vdop) self._testDOP(pe, pdop, hdop, vdop) def test_horizontalAndVerticalSet(self) -> None: """ The PDOP is correctly determined from HDOP and VDOP. """ hdop, vdop = 1.0, 1.0 pdop = (hdop**2 + vdop**2) ** 0.5 pe = base.PositionError(hdop=hdop, vdop=vdop) self._testDOP(pe, pdop, hdop, vdop) class BeaconInformationTests(TestCase): """ Tests for L{twisted.positioning.base.BeaconInformation}. """ def test_minimal(self) -> None: """ For an empty beacon information object, the number of used beacons is zero, the number of seen beacons is zero, and the repr of the object reflects that. """ bi = base.BeaconInformation() self.assertEqual(len(bi.usedBeacons), 0) expectedRepr = ( "<BeaconInformation (" "used beacons (0): [], " "unused beacons: [])>" ) self.assertEqual(repr(bi), expectedRepr) satelliteKwargs = {"azimuth": 1, "elevation": 1, "signalToNoiseRatio": 1.0} def test_simple(self) -> None: """ Tests a beacon information with a bunch of satellites, none of which used in computing a fix. """ def _buildSatellite(**kw: float) -> base.Satellite: kwargs = dict(self.satelliteKwargs) kwargs.update(kw) return base.Satellite(**kwargs) beacons = set() for prn in range(1, 10): beacons.add(_buildSatellite(identifier=prn)) bi = base.BeaconInformation(beacons) self.assertEqual(len(bi.seenBeacons), 9) self.assertEqual(len(bi.usedBeacons), 0) self.assertEqual( repr(bi), "<BeaconInformation (used beacons (0): [], " "unused beacons: [" "<Satellite (1), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (2), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (3), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (4), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (5), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (6), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (7), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (8), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (9), azimuth: 1, elevation: 1, snr: 1.0>" "])>", ) def test_someSatellitesUsed(self) -> None: """ Tests a beacon information with a bunch of satellites, some of them used in computing a fix. """ bi = base.BeaconInformation() for prn in range(1, 10): satellite = base.Satellite(identifier=prn, **self.satelliteKwargs) bi.seenBeacons.add(satellite) if prn % 2: bi.usedBeacons.add(satellite) self.assertEqual(len(bi.seenBeacons), 9) self.assertEqual(len(bi.usedBeacons), 5) self.assertEqual( repr(bi), "<BeaconInformation (used beacons (5): [" "<Satellite (1), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (3), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (5), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (7), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (9), azimuth: 1, elevation: 1, snr: 1.0>], " "unused beacons: [" "<Satellite (2), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (4), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (6), azimuth: 1, elevation: 1, snr: 1.0>, " "<Satellite (8), azimuth: 1, elevation: 1, snr: 1.0>])>", ) class PositioningBeaconTests(TestCase): """ Tests for L{base.PositioningBeacon}. """ def test_interface(self) -> None: """ Tests that L{base.PositioningBeacon} implements L{IPositioningBeacon}. """ implements = IPositioningBeacon.implementedBy(base.PositioningBeacon) self.assertTrue(implements) verify.verifyObject(IPositioningBeacon, base.PositioningBeacon(1)) def test_repr(self) -> None: """ Tests the repr of a positioning beacon. """ self.assertEqual(repr(base.PositioningBeacon("A")), "<Beacon (A)>") class SatelliteTests(TestCase): """ Tests for L{twisted.positioning.base.Satellite}. """ def test_minimal(self) -> None: """ Tests a minimal satellite that only has a known PRN. Tests that the azimuth, elevation and signal to noise ratios are L{None} and verifies the repr. """ s = base.Satellite(1) self.assertEqual(s.identifier, 1) self.assertIsNone(s.azimuth) self.assertIsNone(s.elevation) self.assertIsNone(s.signalToNoiseRatio) self.assertEqual( repr(s), "<Satellite (1), azimuth: None, " "elevation: None, snr: None>" ) def test_simple(self) -> None: """ Tests a minimal satellite that only has a known PRN. Tests that the azimuth, elevation and signal to noise ratios are correct and verifies the repr. """ s = base.Satellite( identifier=1, azimuth=270.0, elevation=30.0, signalToNoiseRatio=25.0 ) self.assertEqual(s.identifier, 1) self.assertEqual(s.azimuth, 270.0) self.assertEqual(s.elevation, 30.0) self.assertEqual(s.signalToNoiseRatio, 25.0) self.assertEqual( repr(s), "<Satellite (1), azimuth: 270.0, " "elevation: 30.0, snr: 25.0>" )