update server
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import importlib.util
|
||||
import csv
|
||||
import io
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import types
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
MODULE_PATH = Path(__file__).resolve().parents[1] / "core" / "identification_config.py"
|
||||
SPEC = importlib.util.spec_from_file_location(
|
||||
"identification_config_under_test", MODULE_PATH
|
||||
)
|
||||
IDENTIFICATION_CONFIG = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(IDENTIFICATION_CONFIG)
|
||||
validate_identification_config = IDENTIFICATION_CONFIG.validate_identification_config
|
||||
parse_identification_config_csv = IDENTIFICATION_CONFIG.parse_identification_config_csv
|
||||
download_identification_config = IDENTIFICATION_CONFIG.download_identification_config
|
||||
|
||||
|
||||
VALID_CONFIG = {
|
||||
"q_in_val": 50.0,
|
||||
"dt": 0.1,
|
||||
"n_order": 6,
|
||||
"t_c": 2.5,
|
||||
"levels": [10, 20, 30, 40, 50, 60, 70, 80],
|
||||
"dead_area": 240.0,
|
||||
"xa_full": 1000.0,
|
||||
"V_val": 5.0,
|
||||
"repeat": 2,
|
||||
}
|
||||
|
||||
|
||||
def config_csv(config):
|
||||
output = io.StringIO(newline="")
|
||||
writer = csv.writer(output)
|
||||
writer.writerow(("parameter", "value"))
|
||||
for key in (
|
||||
"q_in_val", "dt", "n_order", "t_c", "levels", "dead_area",
|
||||
"xa_full", "V_val", "repeat"):
|
||||
value = config[key]
|
||||
if key == "levels":
|
||||
value = ",".join(str(item) for item in value)
|
||||
writer.writerow((key, value))
|
||||
return output.getvalue()
|
||||
|
||||
|
||||
class IdentificationConfigTests(unittest.TestCase):
|
||||
def test_accepts_and_normalizes_valid_config(self):
|
||||
result = validate_identification_config(VALID_CONFIG)
|
||||
self.assertEqual(result["repeat"], 2)
|
||||
self.assertEqual(result["levels"], [
|
||||
10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0
|
||||
])
|
||||
|
||||
def test_rejects_missing_field(self):
|
||||
config = dict(VALID_CONFIG)
|
||||
config.pop("repeat")
|
||||
with self.assertRaisesRegex(ValueError, "缺少"):
|
||||
validate_identification_config(config)
|
||||
|
||||
def test_parses_parameter_value_csv(self):
|
||||
result = parse_identification_config_csv(config_csv(VALID_CONFIG))
|
||||
self.assertEqual(result, VALID_CONFIG)
|
||||
|
||||
def test_rejects_non_power_of_two_levels(self):
|
||||
config = dict(VALID_CONFIG, levels=[10, 20, 30])
|
||||
with self.assertRaisesRegex(ValueError, "2 的整数次幂"):
|
||||
validate_identification_config(config)
|
||||
|
||||
def test_rejects_symbol_period_shorter_than_sample_period(self):
|
||||
config = dict(VALID_CONFIG, dt=0.1, t_c=0.05)
|
||||
with self.assertRaisesRegex(ValueError, "t_c 必须大于等于 dt"):
|
||||
validate_identification_config(config)
|
||||
|
||||
def test_rejects_travel_scan_above_xa_full(self):
|
||||
config = dict(VALID_CONFIG, xa_full=999.0)
|
||||
with self.assertRaisesRegex(ValueError, "1000"):
|
||||
validate_identification_config(config)
|
||||
|
||||
def test_rejects_dead_area_at_or_above_xa_full(self):
|
||||
config = dict(VALID_CONFIG, dead_area=1000.0)
|
||||
with self.assertRaisesRegex(ValueError, "dead_area"):
|
||||
validate_identification_config(config)
|
||||
|
||||
def test_download_requests_customer_config_and_validates_it(self):
|
||||
calls = []
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, body=None, text=None):
|
||||
self.body = body
|
||||
self.text = text
|
||||
|
||||
def raise_for_status(self):
|
||||
return None
|
||||
|
||||
def json(self):
|
||||
return self.body
|
||||
|
||||
requests_module = types.ModuleType("requests")
|
||||
requests_module.RequestException = Exception
|
||||
|
||||
def post(url, json, timeout):
|
||||
calls.append(("post", url, json, timeout))
|
||||
return FakeResponse({"success": True, "url": "https://temp/config"})
|
||||
|
||||
def get(url, timeout):
|
||||
calls.append(("get", url, timeout))
|
||||
return FakeResponse(text=config_csv(VALID_CONFIG))
|
||||
|
||||
requests_module.post = post
|
||||
requests_module.get = get
|
||||
api_module = types.ModuleType("api")
|
||||
api_module.data_record_url = "https://cloud/data_record"
|
||||
api_module.the_folder = "客户A"
|
||||
|
||||
with patch.dict(sys.modules, {
|
||||
"requests": requests_module,
|
||||
"api": api_module,
|
||||
}):
|
||||
result = download_identification_config(timeout=7)
|
||||
|
||||
self.assertEqual(result["repeat"], 2)
|
||||
self.assertEqual(calls[0], (
|
||||
"post",
|
||||
"https://cloud/data_record",
|
||||
{"type": "getIdentificationConfig", "deviceId": "客户A"},
|
||||
7,
|
||||
))
|
||||
self.assertEqual(calls[1], ("get", "https://temp/config", 7))
|
||||
|
||||
def test_download_reports_cloud_rejection(self):
|
||||
class FakeResponse:
|
||||
def raise_for_status(self):
|
||||
return None
|
||||
|
||||
def json(self):
|
||||
return {"success": False, "errMsg": "配置不存在"}
|
||||
|
||||
requests_module = types.ModuleType("requests")
|
||||
requests_module.RequestException = Exception
|
||||
requests_module.post = lambda *args, **kwargs: FakeResponse()
|
||||
api_module = types.ModuleType("api")
|
||||
api_module.data_record_url = "https://cloud/data_record"
|
||||
api_module.the_folder = "客户A"
|
||||
|
||||
with patch.dict(sys.modules, {
|
||||
"requests": requests_module,
|
||||
"api": api_module,
|
||||
}):
|
||||
with self.assertRaisesRegex(ValueError, "配置不存在"):
|
||||
download_identification_config()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user