31.2. 测试结果评估 #
某些安装正确且功能完备的 PostgreSQL 实例,可能会因为平台特有因素而在部分回归测试中“失败”,例如浮点表示或消息措辞不同。目前这些测试是通过把输出与参考系统生成的输出做简单的 diff 比较来评估的,因此结果会对细微的系统差异很敏感。报告某项测试“失败”时,请务必检查预期结果与实际结果之间的差异;你可能会发现这些差异并不重要。尽管如此,我们仍努力在所有受支持平台上维护准确的参考文件,因此原则上应期待所有测试都能通过。
回归测试的实际输出位于 src/test/regress/results
目录中的文件里。测试脚本使用 diff 将每个输出文件与存放在 src/test/regress/expected 目录中的参考输出进行比较。所有差异都会保存在
src/test/regress/regression.diffs 中供你检查。(运行核心测试以外的测试套件时,这些文件当然会出现在相应的子目录中,而不是 src/test/regress。)
如果不喜欢默认使用的 diff 选项,可设置环境变量
PG_REGRESS_DIFF_OPTS,例如
PG_REGRESS_DIFF_OPTS='-c'。(或者如果你愿意,也可以自己运行 diff。)
如果由于某种原因,某个特定平台在某个测试上产生了“失败”,但对输出的检查令你相信结果是有效的,那么可以新增一个比较文件,让后续测试运行不再报告该失败。详情见第 31.3 节。
31.2.1. 错误消息差异 #
某些回归测试包含故意构造的非法输入值。错误消息可能来自 PostgreSQL 代码,也可能来自宿主平台的系统例程。在后一种情况下,消息会因平台而异,但应反映相近的信息。这类消息差异会导致回归测试显示为“失败”,但可以通过检查确认其有效性。
31.2.2. 区域设置差异 #
如果你针对一个排序区域设置不是 C 的服务器运行测试,就可能因为排序顺序不同而出现差异,并导致后续失败。回归测试套件通过提供备用结果文件来处理这个问题;这些文件已知可以覆盖大量区域设置。
使用临时安装方法时,要在不同区域设置下运行测试,可在
make 命令行上传递合适的区域设置相关环境变量,例如:
make check LANG=de_DE.utf8
(回归测试驱动器会取消设置 LC_ALL,因此不能用该变量选择区域设置。)如果不使用区域设置,要么取消所有与区域设置相关的环境变量(或将它们设为 C),要么使用下面这个特殊调用:
make check NO_LOCALE=1
针对现有安装运行测试时,区域设置由现有安装决定。要改变它,需要在初始化数据库集簇时向 initdb 传入合适选项,使用另一种区域设置。
一般来说,建议在计划用于生产环境的区域设置下运行回归测试,因为这样可以覆盖实际将在生产中使用的区域设置和编码相关代码部分。根据操作系统环境不同,可能会出现失败,但至少你会知道在真实应用运行时应当预期哪些与区域设置相关的行为。
31.2.3. 日期和时间差异 #
大多数日期和时间结果依赖于时区环境。参考文件是在时区
America/Los_Angeles 下生成的,如果测试未在该时区设置下运行,就会出现表面上的失败。回归测试驱动器会将环境变量
PGTZ 设为 America/Los_Angeles,这通常能够确保获得正确结果。
31.2.4. 浮点差异 #
某些测试涉及根据表列计算 64 位浮点数(double
precision)。我们已经观察到涉及 double
precision 列数学函数的结果存在差异。float8 和
geometry 测试尤其容易在不同平台之间,甚至在不同编译器优化设置下出现细微差异。要判断这些通常出现在小数点右侧第 10 位附近的差异究竟是否重要,需要人工目测比较。
某些系统把负零显示为 -0,而另一些只显示
0。
某些系统对 pow() 和 exp()
发出错误的方式,与当前 PostgreSQL 代码所预期的机制不同。
31.2.5. 行顺序差异 #
你可能会看到这样的差异:同样的行在输出中的顺序与预期文件中的顺序不同。在大多数情况下,严格说来这并不是缺陷。大多数回归测试脚本并没有细致到为每一个 SELECT 都使用 ORDER BY,因此按 SQL 规范,它们的结果行顺序并没有明确定义。实际上,由于我们看到的是同一软件在同一数据上执行相同查询,通常在所有平台上都会得到相同的结果顺序,所以缺少 ORDER BY 并不是问题。不过,有些查询确实会表现出跨平台的顺序差异。针对已安装服务器测试时,非 C 区域设置或非默认参数设置,例如自定义的 work_mem 值或规划器代价参数,也可能导致顺序差异。
因此,如果你看到顺序差异,一般无需担心,除非查询确实包含
ORDER BY 而你的结果违反了它。不过,仍请报告该问题,这样我们可以为那个特定查询加上 ORDER BY,以在后续版本中消除这种虚假的“失败”。
你可能会好奇,为什么我们不显式地为所有回归测试查询排序,从而一劳永逸地解决这个问题。原因在于,那样反而会降低回归测试的价值,因为测试会倾向于覆盖能产生有序结果的查询计划类型,而排除那些不能产生有序结果的计划类型。
31.2.6. 栈深度不足 #
如果 errors 测试在执行
select infinite_recurse() 命令时导致服务器崩溃,这意味着平台对进程栈大小的限制比 max_stack_depth 参数所表明的更小。可通过在更高的栈大小限制下运行服务器来修复(对于 max_stack_depth 的默认值,建议 4MB)。如果做不到,另一种办法是减小 max_stack_depth
的值。
在支持 getrlimit() 的平台上,服务器应自动选择
max_stack_depth 的安全值;因此,除非你手工覆盖了该设置,否则这类失败就是一个应报告的缺陷。
31.2.7. “random”测试 #
random 测试脚本本来就是要产生随机结果的。在极少数情况下,这会导致该回归测试失败。输入:
diff results/random.out expected/random.out
只应产生一行或几行差异。除非 random 测试反复失败,否则不必担心。
31.2.8. 配置参数 #
在针对现有安装运行测试时,某些非默认参数设置可能导致测试失败。例如,改变 enable_seqscan 或
enable_indexscan 等参数,可能导致计划发生变化,进而影响使用 EXPLAIN 的测试结果。