(go) ssh.AuthMethod 的深度平等

(go) Deep equality for ssh.AuthMethod

我正在使用 crypto/ssh 包,我正在尝试为构造 ClientConfig 的方法编写单元测试。

单元中的断言之一是返回的 ClientConfig 与预期深度相等。 断言失败,因为 ClientConfigAuthHostKeyCallback 字段并不完全相等。 HostKeyCallback 被硬编码为 ssh.InsecureIgnoreHostKey()。 我现在正在测试的唯一身份验证方法是使用密码,我已验证密码字符串是否正确。

我试图在操场上乱搞(参见 here),但我不明白为什么在这些情况下没有深度平等。

package main

import (
    "fmt"
    "reflect"

    "golang.org/x/crypto/ssh"
)

func main() {
    pass := "bar"
    auth := []ssh.AuthMethod{ssh.Password(pass)}
    authLiteral := []ssh.AuthMethod{ssh.Password("bar")}
    if reflect.DeepEqual(authLiteral, auth) {
        fmt.Println("authentication methods are equal")
    } else {
        fmt.Println("authentication methods are not equal")
    }

    callback1 := ssh.InsecureIgnoreHostKey()
    callback2 := ssh.InsecureIgnoreHostKey()
    if reflect.DeepEqual(callback1, callback2) {
        fmt.Println("callbacks are equal")
    } else {
        fmt.Println("callbacks are not equal")
    }
}
authentication methods are not equal
callbacks are not equal

有人可以解释一下这些结果吗? 如果您能建议我如何对这种情况进行单元测试,我也将不胜感激。

作为 Go 实现附带的 , this is formally disallowed. (Still, it might be nice if reflect.DeepEqual,它做了一些我在下面做的事情。因为它是自带实现的,所以实现者可以用专门的知识来写。)

当然,最终,machine-level 实现了一些 指向函数的指针,其参数类型为 T1,T 2, ... Tna 返回值类型为R1, R2, ... Rnr。但是我们没有被告知什么表示。它可能是单个 unsafe.Pointer 值,也可能是 thunk 的某种内联扩展。所以我们不知道这里要比较多少字节。

如果您愿意做出相当危险的/non-portable假设,并在证明不充分时更新它们,那么一种“作弊”的方法这里。我在 Go Playground 上创建了 this example,它产生了所需的输出。这只是偶然,还是这真的适用于你的 Go 实现?

正文也在下方。使用风险自负!

package main

import (
    "fmt"
    "unsafe"
)

func dummy1() {}
func dummy2() {}

func main() {
    fmt.Println("dummy1 == dummy2 =>", qe(dummy1, dummy2))
    fmt.Println("dummy1 == dummy1 =>", qe(dummy1, dummy1))
}

// "questionably equal", for function pointers
func qe(a, b func()) bool {
    pp1 := (*unsafe.Pointer)(unsafe.Pointer(&a))
    pp2 := (*unsafe.Pointer)(unsafe.Pointer(&b))
    p1 := *pp1
    p2 := *pp2
    return p1 == p2
}