mirror of
https://github.com/kk7ds/chirp.git
synced 2024-09-21 18:47:18 +00:00
ad73f0b53f
This makes us include the *structure* of mem.extra in the assertEqualMems() check to make sure it doesn't change before and after a modification.
194 lines
7.0 KiB
Python
194 lines
7.0 KiB
Python
import logging
|
|
|
|
from chirp import chirp_common
|
|
from chirp import errors
|
|
from tests import base
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class TestCaseBruteForce(base.DriverTest):
|
|
def set_and_compare(self, m, **kwargs):
|
|
msgs = self.radio.validate_memory(m)
|
|
if msgs:
|
|
# If the radio correctly refuses memories it can't
|
|
# store, don't fail
|
|
return
|
|
|
|
self.radio.set_memory(chirp_common.FrozenMemory(m))
|
|
ret_m = self.radio.get_memory(m.number)
|
|
|
|
# Damned Baofeng radios don't seem to properly store
|
|
# shift and direction, so be gracious here
|
|
if m.duplex == "split" and ret_m.duplex in ["-", "+"]:
|
|
ret_m.offset = ret_m.freq + \
|
|
(ret_m.offset * int(ret_m.duplex + "1"))
|
|
ret_m.duplex = "split"
|
|
|
|
self.assertEqualMem(m, ret_m, **kwargs)
|
|
|
|
def test_tone(self):
|
|
m = self.get_mem()
|
|
for tone in chirp_common.TONES:
|
|
for tmode in self.rf.valid_tmodes:
|
|
if tmode not in chirp_common.TONE_MODES:
|
|
continue
|
|
elif tmode in ["DTCS", "DTCS-R", "Cross"]:
|
|
continue # We'll test DCS and Cross tones separately
|
|
|
|
m.tmode = tmode
|
|
if tmode == "":
|
|
pass
|
|
elif tmode == "Tone":
|
|
m.rtone = tone
|
|
elif tmode in ["TSQL", "TSQL-R"]:
|
|
if self.rf.has_ctone:
|
|
m.ctone = tone
|
|
else:
|
|
m.rtone = tone
|
|
else:
|
|
self.fail("Unknown tone mode `%s'" % tmode)
|
|
|
|
try:
|
|
self.set_and_compare(m)
|
|
except errors.UnsupportedToneError:
|
|
# If a radio doesn't support a particular tone value,
|
|
# don't punish it
|
|
pass
|
|
|
|
@base.requires_feature('has_dtcs')
|
|
def test_dtcs(self):
|
|
m = self.get_mem()
|
|
m.tmode = "DTCS"
|
|
for code in self.rf.valid_dtcs_codes:
|
|
m.dtcs = code
|
|
self.set_and_compare(m)
|
|
|
|
if not self.rf.has_dtcs_polarity:
|
|
return
|
|
|
|
for pol in self.rf.valid_dtcs_pols:
|
|
m.dtcs_polarity = pol
|
|
self.set_and_compare(m)
|
|
|
|
@base.requires_feature('has_cross')
|
|
def test_cross(self):
|
|
m = self.get_mem()
|
|
m.tmode = "Cross"
|
|
# No fair asking a radio to detect two identical tones as Cross instead
|
|
# of TSQL
|
|
m.rtone = 100.0
|
|
m.ctone = 107.2
|
|
m.dtcs = 506
|
|
m.rx_dtcs = 516
|
|
for cross_mode in self.rf.valid_cross_modes:
|
|
m.cross_mode = cross_mode
|
|
self.set_and_compare(m)
|
|
|
|
@base.requires_feature('valid_duplexes')
|
|
def test_duplex(self):
|
|
m = self.get_mem()
|
|
if 'duplex' in m.immutable:
|
|
self.skipTest('Test memory has immutable duplex')
|
|
for duplex in self.rf.valid_duplexes:
|
|
if duplex not in ["", "-", "+", "split"]:
|
|
continue
|
|
if duplex == 'split':
|
|
self.assertTrue(self.rf.can_odd_split,
|
|
'Radio supports split but does not set '
|
|
'can_odd_split=True in features')
|
|
m.offset = self.rf.valid_bands[0][1] - 100000
|
|
else:
|
|
m.offset = chirp_common.to_kHz(int(m.tuning_step) * 2)
|
|
m.duplex = duplex
|
|
# Ignore the offset because we do some fudging on this and we
|
|
# don't necessarily know the best step to use. What we care about
|
|
# is duplex here.
|
|
self.set_and_compare(m, ignore=['offset'])
|
|
|
|
if self.rf.can_odd_split:
|
|
self.assertIn('split', self.rf.valid_duplexes,
|
|
'Radio claims can_odd_split but split not in '
|
|
'valid_duplexes')
|
|
|
|
@base.requires_feature('valid_skips')
|
|
def test_skip(self):
|
|
mem = self.get_mem()
|
|
lo, hi = self.rf.memory_bounds
|
|
# Walk through several memories, specifically across 8 and 16,
|
|
# as many radio use bitfields for skip flags.
|
|
for i in range(max(5, lo), min(25, hi)):
|
|
# Walk through the skip flags twice each, to make sure we can
|
|
# toggle them on..off..on
|
|
for skip in self.rf.valid_skips * 2:
|
|
m = mem.dupe()
|
|
if 'empty' not in m.immutable:
|
|
m.empty = False
|
|
m.number = i
|
|
m.skip = skip
|
|
self.set_and_compare(m)
|
|
# Delete the memory each time because some radios are
|
|
# dynamically allocated and will run out of space here.
|
|
self.radio.erase_memory(m.number)
|
|
|
|
@base.requires_feature('valid_modes')
|
|
def test_mode(self):
|
|
m = self.get_mem()
|
|
if 'mode' in m.immutable:
|
|
self.skipTest('Test memory has immutable duplex')
|
|
|
|
def ensure_urcall(call):
|
|
lst = self.radio.get_urcall_list()
|
|
lst[0] = call
|
|
self.radio.set_urcall_list(lst)
|
|
|
|
def ensure_rptcall(call):
|
|
lst = self.radio.get_repeater_call_list()
|
|
lst[0] = call
|
|
self.radio.set_repeater_call_list(lst)
|
|
|
|
def freq_is_ok(freq):
|
|
for lo, hi in self.rf.valid_bands:
|
|
if freq > lo and freq < hi:
|
|
return True
|
|
return False
|
|
|
|
successes = 0
|
|
for mode in self.rf.valid_modes:
|
|
self.assertIn(mode, chirp_common.MODES,
|
|
'Radio exposes non-standard mode')
|
|
tmp = m.dupe()
|
|
if mode == "DV" and \
|
|
isinstance(self.radio,
|
|
chirp_common.IcomDstarSupport):
|
|
tmp = chirp_common.DVMemory()
|
|
try:
|
|
ensure_urcall(tmp.dv_urcall)
|
|
ensure_rptcall(tmp.dv_rpt1call)
|
|
ensure_rptcall(tmp.dv_rpt2call)
|
|
except IndexError:
|
|
if self.rf.requires_call_lists:
|
|
raise
|
|
else:
|
|
# This radio may not do call lists at all,
|
|
# so let it slide
|
|
pass
|
|
if mode == "FM" and freq_is_ok(tmp.freq + 100000000):
|
|
# Some radios don't support FM below approximately 30MHz,
|
|
# so jump up by 100MHz, if they support that
|
|
tmp.freq += 100000000
|
|
|
|
tmp.mode = mode
|
|
|
|
if self.rf.validate_memory(tmp):
|
|
# A result (of error messages) from validate means the radio
|
|
# thinks this is invalid, so don't fail the test
|
|
LOG.warning('Failed to validate %s: %s' % (
|
|
tmp, self.rf.validate_memory(tmp)))
|
|
continue
|
|
|
|
# Ignore tuning_step because changing modes may cause step changes
|
|
# in some radios
|
|
self.set_and_compare(tmp, ignore=['tuning_step'])
|
|
successes += 1
|