调试golang测试

调试某个go test程序的时候,需要实现confirm/approve功能: 测试完testCase1之后(或者说是某个断点),用户输入yes,执行下一个case,输入no, 则退出整个测试。 分析 下意识的觉得这个很好实现,调用fmt.Scan应该就OK了。 但是写的时候才发现,go test 会强制重定向os.Stdin = /dev/null忽略所有的 stdin输入, 所以没法使用 fmt.Scan来等待键盘(用户)的输入: 1 2 3 4 5 // fmt.Scan reads from os.Stdin, which is set to /dev/null when testing. // Tests should be automated and self-contained anyway, so you don't want // to read from stdin. // Either use an external file, a bytes.Buffer, or a strings.Reader and // call scan.Fscan if you want to test **the literal** `scan` Function. 解决方案 可以参考事件驱动,使用named pipes来实现confirm/approve功能: ...

October 14, 2020 · datewu

SSH代理(Agent)

问题 已知本地local可以ssh到server A和B, 问如何从server A ssh到server B,以及如何在server A 和B之间使用scp互传文件 ? 解决方案 配置ssh_config然后使用 ssh-add命令指定使用ssh agent可以很安全和高效的解决上面的两个问题。 配置ssh_config 注意看注释,下面脚本所有的操作和配置都是在 本地local上执行的: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 vi .ssh/config ## 修改配置 添加forward agent HOST server-A HostName 1.2.3.4 User root IdentityFile ~/.ssh/serverA ForwardAgent yes # 现在 serverA可以和local本机的agent通信啦 HOST server-B HostName 6.7.8.9 User root IdentityFile ~/.ssh/serverB ForwardAgent yes # 现在 serverB可以和local本机的ssh agent 通信啦 rg Forward /etc/ssh/ssh_config ## 检查全局的forwordagent配置有没有被覆盖 echo "$SSH_AUTH_SOCK" ## 查看本地ssh agent是否在运行 ssh-add -L ## 查看/操作/删除 ssh agent hold的keys ssh-add -K li ssh-add -K ~/.ssh/serverA ## 给agent serverA 密钥,使得serverB 可以“使用” 这个密钥 ssh-add -K ~/.ssh/serverB ## 给agent serverB密钥,使得serverA可以“使用”这个密钥 ssh-add -K ~/.ssh/github ## 给阿根廷 github密钥,使得serverA, serverB都可以ssh github,方便测试 ssh-add -L 验证github 也是在本机local操作,以github作为测试目标: ...

April 12, 2020 · datewu

nopCloser函数

update: ioutil逐渐被io 取代。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package ioutil // import "io/ioutil" func NopCloser(r io.Reader) io.ReadCloser NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r. As of Go 1.16, this function simply calls io.NopCloser. package io // import "io" func NopCloser(r Reader) ReadCloser NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r. 最近使用baloo写集成测试,遇到了个需求, 在unmarshalrespones之后(或者之前)还要再输出一次response的纯文本格式供debug参考。 即需要多次读http.Resp.Body。 问题 response.Body 只能读一次,读完之后再进行read操作就会遇到EOF error。 分析问题 模糊记得baloo在一次请求中能多次(JSON() 和 String())读取response.Body内容。 仔细去看了下baloo的源代码,发现baloo自己在内部 封装了一个对象 http.RawResonse ,使用了 iouti.NopCloser函数重新填充了res.Body: 1 2 3 4 5 6 7 8 9 10 func readBodyJSON(res *http.Response) ([]byte, error) { body, err := ioutil.ReadAll(res.Body) if err != nil { return []byte{}, err } // Re-fill body reader stream after reading it res.Body = ioutil.NopCloser(bytes.NewBuffer(body)) return body, err } 解决方案 有了 ioutil.NopCloser函数,可以很快速的写出debugPlugin: ...

April 17, 2019 · datewu

无法创建macvlan设备

最近给客户调试 macvlan network时,遇到了Linux kernel 报错 SIOCSIFFKAGS: Device or resource busy. 无法创建网络device。 结果长时间的debug分析, 发现问题是高并发压测 创建和释放macvlan device的时候,设备的mac address出现了重复。 ps:这个问题只出现在 macvlannetwork 的设备中。 可以用下面的shell脚本来复现macvlan Device or resource busy的错误: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/bin/bash function setup { i=$1 ip l a m$i address 00:40:2F:4D:5E:6F link eth0 type macvlan mode bridge ip netns add ns$i ip l set m$i netns ns$i sleep 1 ip netns exec ns$i ifconfig m$i 10.0.0.$((i+1))/24 up echo $? } echo cleaning up ip -all netns d echo creating netsnses for i in `seq $1`; do echo $i.... #setup $i & setup $i done 如果把 macvlan 类型改为 dummy (上面脚本第5行 type macvlan 改为 type dummy) ,即使 MAC address 重复也不会引发kernel 报错。 ...

March 7, 2019 · datewu

Pod生命周期和Liveness的区别

今天测试给我反馈了一个pod问题,测试给出的 use case 描述如下: 配置一个nginx的web服务; 在生命周期中选择http协议,端口配置80,路径配置/errorpath; 服务中pod能正常启动; 预期在pod的事件中应该有一个“FailedPostStartHook”错误信息。 测试人员发现,第4点的预期没有达到,pod 正常启动了,却没有 FailedPostStarHook事件出现。 简单分析了一下,我发现是测试人员把pod的lifecycle和 pod的liveness/readiness 诺混淆了,从而写出了错的test case。 Lifecycle handlers 首先回顾下pod lifecycle的作用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 kubectl explain pod.spec.containers.lifecycle.postStart RESOURCE: postStart <Object> DESCRIPTION: PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/ container-lifecycle-hooks/#container-hooks/ Handler defines a specific action that should be taken 简单翻译下就是说, kubernetes 提供的pod start和exit的 lifecycle hooks 方便开发人员hooked到 ...

September 18, 2018 · datewu