proto.Unmarshal 测试不一致地失败
proto.Unmarshal test fails inconsistently
我有一些 Redis 代码依赖于 marshalling/unmarshalling 数据的 Proto 标准。我使用 gomega 编写了以下测试来测试 proto.Unmarshal
:
b64Decoded, err := base64.StdEncoding.DecodeString("derp")
Expect(err).ShouldNot(HaveOccurred())
var item testRecord
err = proto.Unmarshal(b64Decoded, &item)
Expect(err).Should(HaveOccurred())
Expect(err.Error()).Should(Equal("proto:\u00a0cannot parse invalid wire-format data"))
然而,最终的断言失败了,因为预期的错误字符串是 proto: cannot parse invalid wire-format data
。这里显而易见的解决方案是更改它,当我这样做时,错误就会消失。直到我修改测试并重新运行它,在这种情况下,测试再次失败,告诉我字符串应该是 proto:\u00a0cannot parse invalid wire-format data
。这个循环无限继续下去。那么,我在这里做错了什么以及如何解决这个问题?
这个问题跟你想的不太一样; protobuf
包在输出错误时随机选择 space 或 \u00a0
(我相信它基于二进制的散列)。你可以看到这个 here:
// Deliberately introduce instability into the error message string to
// discourage users from performing error string comparisons.
if detrand.Bool() {
return "proto: " // use non-breaking spaces (U+00a0)
} else {
return "proto: " // use regular spaces (U+0020)
}
所以您遇到的问题是故意的,旨在阻止用户执行您正在尝试的操作(依赖于保持不变的错误)。你只在更改测试时看到它的原因(我猜,不是每次更改它时)是 Go
将缓存测试结果(默认情况下,测试仅 运行 当有些东西变了)。
关于你能做些什么,我首先建议考虑这个测试是否真的有必要。软件包作者特别指出错误不稳定,因此在发布新版本 google.golang.org/protobuf/proto
时,以这种方式进行比较可能会中断。
protobuf
包测试通过调用 detrand.Disable()
解决这个问题(例如 here). You cannot do this because google.golang.org/protobuf/internal/detrand
is under internal
and, as such, not accessible.
如果您真的想解决这个问题,最简单的方法可能是 strings.Contains
。
我有一些 Redis 代码依赖于 marshalling/unmarshalling 数据的 Proto 标准。我使用 gomega 编写了以下测试来测试 proto.Unmarshal
:
b64Decoded, err := base64.StdEncoding.DecodeString("derp")
Expect(err).ShouldNot(HaveOccurred())
var item testRecord
err = proto.Unmarshal(b64Decoded, &item)
Expect(err).Should(HaveOccurred())
Expect(err.Error()).Should(Equal("proto:\u00a0cannot parse invalid wire-format data"))
然而,最终的断言失败了,因为预期的错误字符串是 proto: cannot parse invalid wire-format data
。这里显而易见的解决方案是更改它,当我这样做时,错误就会消失。直到我修改测试并重新运行它,在这种情况下,测试再次失败,告诉我字符串应该是 proto:\u00a0cannot parse invalid wire-format data
。这个循环无限继续下去。那么,我在这里做错了什么以及如何解决这个问题?
这个问题跟你想的不太一样; protobuf
包在输出错误时随机选择 space 或 \u00a0
(我相信它基于二进制的散列)。你可以看到这个 here:
// Deliberately introduce instability into the error message string to
// discourage users from performing error string comparisons.
if detrand.Bool() {
return "proto: " // use non-breaking spaces (U+00a0)
} else {
return "proto: " // use regular spaces (U+0020)
}
所以您遇到的问题是故意的,旨在阻止用户执行您正在尝试的操作(依赖于保持不变的错误)。你只在更改测试时看到它的原因(我猜,不是每次更改它时)是 Go
将缓存测试结果(默认情况下,测试仅 运行 当有些东西变了)。
关于你能做些什么,我首先建议考虑这个测试是否真的有必要。软件包作者特别指出错误不稳定,因此在发布新版本 google.golang.org/protobuf/proto
时,以这种方式进行比较可能会中断。
protobuf
包测试通过调用 detrand.Disable()
解决这个问题(例如 here). You cannot do this because google.golang.org/protobuf/internal/detrand
is under internal
and, as such, not accessible.
如果您真的想解决这个问题,最简单的方法可能是 strings.Contains
。