文件最后提交记录最后更新时间
8 个月前
README

Discovery 测试模块总结

概述

tests/discovery/ 目录包含了设备发现和 CSR(配置状态寄存器)解析相关的核心功能测试,主要包括应用模式(App Schema)、CSR 解析器、CSR 工具函数和根接口四个方面的测试。该模块测试了设备发现流程中的核心组件,确保 CSR 文件能够正确解析并生成可用的设备对象组数据,为设备管理提供基础支持。

源代码结构

对应的源代码位于 src/discovery/ 目录:

  • csr_parser.h / csr_parser.cpp: CSR 解析器核心实现

    • parse(): 主解析函数,执行完整的解析流程
    • parse_task: 解析任务基类,实现任务链式执行
    • match_task: 拓扑匹配任务(总线映射)
    • rename_task: 对象重命名任务(对象名映射)
    • append_task: 对象追加任务(Connector 预处理)
    • arrange_task: 对象排列任务(依赖关系分析)
    • analyze_task: 对象分析任务(对象解析和函数分发)
    • raw_data_t: 原始数据结构,存储解析过程中的中间数据
    • 支持函数调用解析、属性引用/同步转换、表达式处理
  • csr_utils.h / csr_utils.cpp: CSR 工具函数实现

    • 类型判断函数:is_sync()、is_ref()、is_func_call()、is_ref_presence()
    • 目标解析函数:get_sync_targets()、get_ref_targets()
    • 字符串替换函数:replace_sync_objects()、replace_ref_object()
    • 拓扑转换函数:convert_topology()
    • 属性表达式提取:get_prop_expr()
    • 辅助函数:get_class_name()、get_connector_position()、is_prop_type_integer()
    • Schema 集成函数:get_instance_info()、get_property_intf()
    • object_group_data: 对象组数据管理类(单例模式)
      • 对象保存和检索(按 position 和 owner 分组)
      • 拓扑数据管理
      • 函数对象处理
      • 设备对象管理
      • 生命周期管理(LifeCycleId)
  • app_schema.h / app_schema.cpp: 应用模式管理实现

    • app_schema: 应用模式单例类
      • init(): 初始化应用路径
      • load(): 加载 Schema 文件
      • get_class_info(): 获取类信息(应用名、路径)
      • get_property_intf(): 获取属性接口名
      • get_property_type(): 获取属性类型
      • get_property_origin_name(): 获取属性原始名称(title)
    • 支持路径模板替换、上下文变量替换
  • root_interface.h / root_interface.cpp: 根接口实现

    • root_interface: D-Bus 根接口(bmc.dev)
      • add_device(): 添加设备(CSR 解析 → 设备管理 → 对象组创建)
      • remove_device(): 删除设备(设备管理 → 对象组注销)
      • create_object_group(): 创建对象组对象
    • 集成设备管理和 CSR 解析
  • object_group.h / object_group.cpp: 对象组对象实现

    • object_group: D-Bus 对象组对象
    • object_group_root: 对象组根对象
    • 提供对象组接口(object_group_interface)

测试文件说明

1. test_app_schema.cpp - 应用模式测试

测试应用模式(App Schema)系统的核心功能,应用模式用于管理设备类定义、属性定义和路径模板,该文件包含了 54 个测试用例:

类信息查询测试(get_class_info)

  • 成功场景

    • 基本类信息查询(ChassisFruCtrl、FruCtrl、ChildFruCtrl)
    • 路径模板替换(支持上下文变量)
    • 上下文键值大小写不敏感匹配(全小写、全大写、混合大小写)
  • 边界情况

    • 类不存在的情况
    • 空上下文的情况(返回未替换的路径模板)
    • 复杂路径模板(父子关系、多级路径)
    • Component 类查询

属性接口查询测试(get_property_intf)

  • 查询属性所属的接口名称
  • 类不存在的情况
  • 属性不存在的情况
  • 多接口属性的处理(返回第一个匹配的接口)
  • 空接口列表的处理(Event 类)

属性类型查询测试(get_property_type)

  • 查询属性的数据类型(String、U8、U16 等)
  • 类不存在的情况
  • 属性不存在的情况
  • Func 类返回空字符串
  • 多种类型的属性(allOf 中的多种类型)

属性原始名称查询测试(get_property_origin_name)

  • 查询属性的原始名称(通过 title 字段)
  • 带 title 的属性返回 title 值
  • 不带 title 的属性返回空字符串
  • 类或属性不存在的情况

Schema 加载测试(load)

  • 正常加载

    • 加载多个路径
    • 空路径列表处理
    • 通过 init 方法加载多个应用路径
  • 错误处理

    • 不存在的路径(记录错误但不抛异常)
    • 文件作为目录处理
    • 不存在的 schema 文件
    • 无效的 JSON 格式
    • 缺失字段处理(无 defs、无 properties、无 interfaces、无 path)
    • 类型错误处理(非对象 defs、非对象 properties、非字符串 path 等)
    • 非数组 allOf 和非字符串 $ref
    • 空 schema 文件

单例模式测试

  • 验证 get_instance 返回同一个实例

2. test_csr_parser.cpp - CSR 解析器测试

CSR 解析器是设备发现的核心组件,负责解析 CSR 文件并生成对象组数据,该文件包含了 35 个测试用例:

对象排列任务测试(arrange_task)

  • 依赖关系分析

    • 统计对象的引用计数
    • 识别被引用对象
    • 构建对象创建队列(按依赖顺序排序)
  • 排序算法

    • 无依赖对象优先
    • 被引用对象在引用对象之前
    • 多级依赖关系的正确处理

CSR 解析测试(parse)

  • 基础解析

    • 解析不含设备对象的 CSR 文件
    • 解析含设备对象的 CSR 文件
    • 对象分组(cooling、general_hardware、frudata、event 等)
    • 对象属性提取和序列化
    • 扩展属性处理(Bom、BoardId、AuxId 等)
  • 对象组数据验证

    • Owners 列表正确性
    • ObjectIdentifier 正确性
    • 通过 D-Bus 接口查询对象组数据
    • LifeCycleId 管理

函数调用解析测试(Func Call Parsing)

  • 基础函数调用

    • 简单函数调用($Func_test({x: 1, y: 2}))
    • 嵌套函数调用($Func_outer({nested: $Func_inner({z: 1})}))
    • 混合参数(引用、同步、静态值)
    • 函数调用转换为 $func: 格式
  • 函数参数类型

    • 引用参数(#/Object.Property)
    • 同步参数(<=/Object.Property)
    • 静态值参数
    • 混合参数类型的函数
  • 函数对象分发

    • 函数对象创建和分发
    • 同组件内引用转换为 $local: 格式
    • 跨组件同步转换为 $sync: 格式
    • 多应用函数分发(同一函数被多个应用使用)

拓扑匹配测试(Topology Matching)

  • 拓扑解析

    • Anchor 节点识别
    • 总线映射(ManagementTopology 中的 Buses 与 Connector 中的 Buses 匹配)
    • 总线数量不匹配的处理(记录警告但不抛异常)
  • 拓扑数据结构

    • 拓扑信息的保存和检索
    • 连接器预处理(Connector 对象)

变量替换测试

  • CSR 文件中的变量替换(${VariableName})
  • DataVersion、FormatVersion 等变量的替换

属性引用和同步测试

  • 引用属性(Reference)

    • 对象引用(#/Object)
    • 属性引用(#/Object.Property)
    • 引用转换为 $ref: 格式(带 Service 和 Path)
  • 同步属性(Sync)

    • 简单同步(<=/Object.Property)
    • 同步属性转换为 $sync: 格式
    • 同步属性默认值处理
    • 同步属性数量限制(最多 10 个)

表达式处理测试

  • 管道符表达式(|> expr(...))
  • 表达式中的条件逻辑
  • 包含 > 符号的值转换为 $const: 格式

边界情况和错误处理

  • 循环引用检测

    • 对象之间的循环引用(Object_A 引用 Object_B,Object_B 引用 Object_A)
    • 自引用检测(对象引用自身属性)
    • 多个父对象检测(一个对象有多个 @Parent 标记)
    • 循环引用不会抛出异常,但会被忽略
  • 特殊对象处理

    • 空对象处理(空属性对象)
    • 父子关系处理(@Parent 标记)
    • Framework 标记的对象(Scanner、Chip 等)
    • 忽略的对象类(Accessor、Scanner、Cont、ContBin、Median)不会出现在解析结果中
  • RENAME_PROPS 处理

    • 特殊类的属性重命名(SmcDfxInfo 等)
  • 同步属性限制

    • 同步属性数量限制(最多 10 个,超过限制会被忽略)
  • 表达式处理

    • 包含 > 符号的值转换为 $const: 格式(避免与管道符表达式冲突)

复杂场景测试

  • 函数调用的复杂嵌套(多级嵌套函数调用)
  • 混合引用和同步属性(同一对象同时使用引用和同步)
  • 多应用对象分发(同一对象被多个应用使用)
  • 同步属性默认值处理(同步属性为空时的默认值)
  • 带设备对象的 CSR 解析(验证设备对象创建和 D-Bus 集成)
  • 使用 test_expr.sr 进行函数解析,覆盖各种函数场景(引用参数、同步参数、混合参数)

任务链测试

  • rename_task 测试

    • 变量替换功能(DataVersion、FormatVersion、SystemId、Slot 等)
    • 对象名重命名(拓扑匹配后的对象名映射)
    • RENAME_PROPS 处理
    • 引用和同步属性中的对象名替换
  • append_task 测试

    • Connector 对象预处理
    • E2P 对象追加
  • parse_task 异常处理测试

    • 无效 CSR 数据结构处理
    • 空 ManagementTopology 处理
    • ManagementTopology 中非数组类型处理
    • 数字类型变量替换处理

3. test_csr_utils.cpp - CSR 工具函数测试

测试 CSR 处理过程中的工具函数,这些函数提供了 CSR 解析所需的基础功能:

类型判断函数

  • is_sync:判断是否为同步属性(<=/ 开头)

    • 支持全局标记(<=/::)
    • 空字符串和普通字符串的区分
  • is_ref:判断是否为引用属性(#/ 开头)

    • 支持全局标记(#/::)
    • 对象引用和属性引用
  • is_func_call:判断是否为函数调用($Func_ 开头)

    • 正确的函数调用格式识别
    • 错误格式的拒绝
  • is_ref_presence:判断是否为 Connector 的 Presence 属性引用

目标解析函数

  • get_sync_targets:解析同步属性目标

    • 简单同步目标(<=/object.prop)
    • 全局同步目标(<=/::object.prop)
    • 多个同步目标(<=/obj1.prop1 <=/obj2.prop2)
    • 带接口名的同步目标(<=/object[interface.name].prop)
    • 空字符串和无效格式的处理
  • get_ref_targets:解析引用属性目标

    • 对象引用(#/object)
    • 属性引用(#/object.prop)
    • 全局引用(#/::object)
    • 带接口名的引用(#/object[interface.name].prop)

字符串替换函数

  • replace_sync_objects:替换同步属性中的对象名

    • 对象名映射替换
    • 全局标记的对象不替换
    • 同名对象多次出现的替换
    • 表达式中的对象名替换(保留管道符和表达式)
  • replace_ref_object:替换引用属性中的对象名

    • 对象引用替换
    • 属性引用替换
    • 全局标记的对象不替换

拓扑转换函数

  • convert_topology:转换拓扑结构
    • 将嵌套的 Buses/Chips 结构转换为数组格式
    • 多级递归处理
    • Anchor 节点识别
    • 空数组处理
    • 无效拓扑处理(无 Anchor)

属性表达式提取函数

  • get_prop_expr:提取属性值中的表达式
    • 管道符表达式提取(|> expr(...))
    • 多个表达式提取
    • 表达式级别限制(默认最多 10 个)
    • 空字符串和无表达式字符串的处理

辅助函数

  • get_class_name:从对象名提取类名(去除后缀数字)

    • 正常对象名(Object_1 -> Object)
    • 边界情况(Object_、_Object、Object_1_2)
  • get_connector_position:从 Connector 获取位置信息

    • 整数位置转换(26 -> "1A")
    • 字符串位置直接返回
    • 缺失位置的处理
  • is_prop_type_integer:判断属性类型是否为整数

    • 基于 schema 查询属性类型
    • 多种类的属性类型判断

对象组数据管理测试(object_group_data)

  • 对象保存和检索

    • save_objects 和 get_objects
    • 多个应用的对象分组
    • 对象属性序列化(ObjectProps)
    • 扩展属性序列化(ObjectExtends)
    • 空对象列表处理
  • 函数对象处理

    • 函数对象保存和分发
    • 多应用函数对象分发
    • 函数对象的参数转换(local:、local:、sync:)
  • 拓扑数据管理

    • save_topology 和 get_topology
    • 拓扑数据的保存和检索
  • Owners 管理

    • get_owners 返回对象的所有者列表
    • 空位置的处理
  • 生命周期管理

    • LifeCycleId 递增机制
    • 每次保存对象时 LifeCycleId 自动递增
  • 设备对象管理

    • is_device_object 判断
    • get_device_object 获取
    • clear_device_objects 清理
  • Connector 特殊处理

    • Connector 类的 SystemId 类型转换(字符串 -> 整数)

Schema 集成函数

  • get_instance_info:获取对象实例信息

    • 基于 schema 获取应用名和路径
    • 不存在的类的处理
    • 带设备对象的实例信息获取
  • get_property_intf:获取属性接口信息

    • 基于 schema 查询
    • 基于 ref_sync_target 查询(优先使用接口名)
    • 不存在的对象和属性的处理

对象组接口测试

  • GetObjects 方法测试

    • 正常对象查询
    • 空 owner 处理
    • 多个对象的正确返回
  • GetTopology 方法测试

    • 拓扑数据查询
    • 不存在位置的查询

并发和边界测试

  • 并发访问测试

    • 模拟并发写入场景
    • 数据一致性验证
  • 边界情况测试

    • 多个 owner 的对象管理
    • 设备对象管理接口测试
    • 清空设备对象测试

4. test_root_interface.cpp - 根接口测试

该文件定义了根接口测试的基础测试类,目前作为测试框架的基础设施使用,为未来的根接口测试预留接口。

测试统计

该测试模块共包含 137 个测试用例:

  • test_app_schema.cpp: 54 个测试用例(应用模式功能)
  • test_csr_parser.cpp: 35 个测试用例(CSR 解析器功能)
  • test_csr_utils.cpp: 48 个测试用例(CSR 工具函数功能)

测试覆盖范围

该测试模块全面覆盖了设备发现和 CSR 解析的核心功能:

  • ✅ 应用模式管理和查询(类信息、属性信息)
  • ✅ CSR 文件解析和对象生成
  • ✅ 对象依赖关系分析和排序
  • ✅ 函数调用解析和转换
  • ✅ 属性引用和同步处理
  • ✅ 拓扑匹配和转换
  • ✅ 变量替换和表达式处理
  • ✅ 对象组数据管理
  • ✅ D-Bus 集成测试
  • ✅ 边界情况和错误处理
  • ✅ 工具函数的正确性

测试工具和基础设施

  • TestBase 继承:所有测试类继承自 mc::test::TestWithEngine,提供统一的测试环境
  • 应用模式初始化:测试中初始化 app_schema,加载测试用的应用定义文件
  • 对象组数据重置:每个测试用例前后重置 object_group_data,确保测试隔离
  • D-Bus 集成:测试中集成了 D-Bus 通信,验证对象组接口的正确性
  • 设备驱动模拟:使用 test_driver 和 mock_topology_driver 模拟设备驱动
  • 测试隔离机制:
    • 每个测试用例后清理对象表(多次清理确保对象被完全删除)
    • 清空 func_collection 缓存(避免测试用例间相互影响)
    • 移除测试驱动(确保驱动状态干净)
    • 对象组数据重置(使用 object_group_data::reset_for_test())
    • 临时文件清理(Schema 加载测试中创建的临时目录和文件)

运行测试

测试使用 Google Test 框架编写,可以通过 meson 构建系统运行:

meson setup builddir
meson compile -C builddir
meson test -C builddir

测试数据依赖

测试依赖于以下测试数据文件:

  • ../tests/tests_data/csr/:CSR 测试文件目录
    • test_expr.sr:函数表达式测试文件
    • test_csr_with_device_objects.sr:带设备对象的 CSR 测试文件
    • 其他 CSR 测试文件
  • ../tests/tests_data/apps/:应用模式定义文件目录
    • test_devices/:测试设备应用定义目录

关键特性

任务链模式

CSR 解析器采用任务链模式(Chain of Responsibility),每个任务负责特定的解析步骤:

  • parse_task 基类:提供任务执行框架(run()、next()、run_and_next())
  • 异常安全:每个任务都有异常处理,任务失败不会中断整个解析流程
  • 链式执行:任务通过 next() 方法链式执行,支持灵活的流程控制
  • 数据共享:所有任务共享 raw_data_t 数据结构,存储解析过程中的中间数据

CSR 解析流程

CSR 解析器实现了完整的解析流程(采用任务链模式):

  1. 拓扑匹配(match_task):匹配拓扑结构,建立总线映射(ManagementTopology.Anchor.Buses ↔ Connector.Buses)
  2. 对象重命名(rename_task):根据总线映射重命名对象,处理对象名映射
  3. 对象追加(append_task):预处理 Connector 对象,追加 E2P 对象
  4. 对象排列(arrange_task):分析对象依赖关系,按正确顺序排列(被引用对象优先)
  5. 对象分析(analyze_task):解析对象属性,处理引用/同步转换,函数对象分发
  6. 对象保存:将解析结果保存到 object_group_data,供对象组接口使用

函数调用解析

系统支持强大的函数调用机制(analyze_task 处理):

  • 函数调用格式:$Func_functionName({param1: value1, param2: value2})
  • 参数类型:支持引用参数(#/Object.Property)、同步参数(<=/Object.Property)、静态值
  • 函数对象分发:函数调用被转换为函数对象(parsed_sr_func_object),并分发到相应的应用
    • 支持多应用函数分发(同一函数被多个应用使用)
    • 函数对象保存在 object_group_data 中,按应用分组
  • 参数转换:同组件内引用转换为 $local: 格式,跨组件同步转换为 $sync: 格式
  • 嵌套函数调用:支持多级嵌套函数调用($Func_outer({nested: $Func_inner({z: 1})}))
  • 函数对象识别:通过类名判断是否为函数对象(Func 类)

对象依赖关系分析

CSR 解析器实现了智能的对象依赖关系分析(arrange_task):

  • 引用计数:统计每个对象被引用的次数(objs_ref_info.ref_count)
  • 依赖排序:被引用对象优先于引用对象创建(引用计数为 0 的对象优先)
  • 循环检测:检测并报告对象间的循环引用(不会抛出异常,但会被忽略)
  • 自引用检测:检测对象的自引用情况(对象引用自身属性)
  • 多父对象检测:检测对象是否有多个父对象(多个 @Parent 标记)
  • 引用对象追踪:记录每个对象被哪些对象引用(objs_ref_info.ref_objects)

Schema 路径模板系统

应用模式支持灵活的路径模板(app_schema::get_class_info()):

  • 路径模板:使用 ${VariableName} 语法定义路径模板
  • 上下文替换:通过上下文字典(context)替换模板变量
    • 支持的变量:SystemId、ManagerId、ChassisId、Id、GroupPosition 等
  • 大小写不敏感:上下文键值匹配不区分大小写(全小写、全大写、混合大小写)
  • 多级路径:支持父子关系的复杂路径模板
  • 默认值处理:未提供的变量使用空字符串或默认值

关键数据结构

  • raw_data_t:解析过程中的原始数据结构

    • m_bus_map:总线名称映射(模板总线名 → connector 总线名)
    • m_extra_buses:额外的总线列表(connector 中未匹配的总线)
    • m_objects_queue:对象创建队列(按依赖顺序排序)
    • m_context:上下文变量(用于变量替换)
    • m_management_topology:管理拓扑(可选)
    • m_objects:对象数据(可选)
  • parsed_sr_object:解析后的对象结构

    • app_name:应用名
    • class_name:类名
    • object_name:对象名
    • path:对象路径
    • object_props:对象属性(序列化为 JSON)
    • extra_props:扩展属性(序列化为 JSON)
    • ref_presence:是否为引用存在性属性
  • parsed_sr_func_object:解析后的函数对象结构

    • app_names:应用名列表(支持多应用)
    • class_name:类名(Func)
    • object_name:对象名
    • object_props:函数属性(包含转换后的参数)
  • instance_info_t:对象实例信息

    • app:应用名
    • path:对象路径
    • framework:是否为框架对象
    • ref_presence:是否为引用存在性属性
    • parent:父对象名
    • object_name:对象名
    • references:引用列表

对象组数据管理

系统实现了完整的对象组数据管理(object_group_data 单例类):

  • 对象分组:按应用(owner)对对象进行分组,每个应用拥有独立的对象列表(二层哈希表:position → owner → object_group_t)
  • 对象标识:使用 ObjectIdentifier(SystemId、ManagerId、ChassisId、Position)标识对象组
  • 生命周期管理:LifeCycleId 自动递增,每次保存对象时递增,追踪对象组变更历史
  • 函数对象管理:函数对象被正确创建和分发到多个应用,支持多应用函数分发
    • 函数参数转换:同组件内引用转换为 $local: 格式,跨组件同步转换为 $sync: 格式
  • 拓扑数据管理:拓扑信息被保存和检索,支持空拓扑和不存在的拓扑查询(独立互斥锁保护)
  • 扩展属性处理:对象扩展属性(extra_props)被序列化到 ObjectExtends 字段(JSON 格式)
  • 特殊类型转换:Connector 类的 SystemId 从字符串自动转换为整数类型
  • 空对象处理:支持保存空对象列表,不会出错
  • 设备对象管理:设备对象映射(position → object_name → abstract_object*),支持设备对象查询和清理
  • 线程安全:使用互斥锁保护对象组数据、拓扑数据和设备对象映射