Pensieve: 1908

2019-08-31 18:01

所观

花了不少时间看TI9, 比赛很精彩, 看到reddit上的人讨论观众素质很无奈.

看完了三个电影:

所玩

塞尔达终于完成900种子了, 后面又迅速刷完重要地点, 完成度到了100%后删游戏了.

Diablo3新赛季开始, 作死玩硬核模式, 选圣教军当主力英雄. 在升级到70的过程中死了两三次, 还好不怎么心疼. 现在巅峰四百多, 大秘境60多, 仍在原始积累中.

aws-sdk-go-v2的单元测试

psyml进度一般(嗯, 我怪TI9和YYF), 花了不少力气在aws-sdk-go-v2的单元测试上, 这儿可以说一下.

在aws-sdk-go里, 一个正常的请求会类似:

svc := kms.New(session.New())
input := &kms.DescribeKeyInput{
  KeyId: aws.String("1234abcd-12ab-34cd-56ef-1234567890ab"),
}

result, err := svc.DescribeKey(input)

即, 新创建一个client, 然后初始化一个输入参数的实例, 接下来直接调用DescribeKey就可以拿到结果了. 对于一个用惯了boto3的人而言, 我觉得这个API挺符合我的认知, 没有使用障碍. 而且, 做单元测试的时候也很方便, 直接mock这个调用就好了.

到了aws-sdk-go-v2, 这个请求会变成:

// Return the Arn of the specified Key
params := kms.DescribeKeyInput{
        KeyId: aws.String(keyid),
}
req := cli.DescribeKeyRequest(&params)
result, err := req.Send(context.Background())

即, 整个请求被分成了两部分, 先用一个DescribeKeyInput实例生成一个DescribeKeyRequest的实例. 然后再调用这个实例的Send方法, 拿到结果.

实话实说, 这种调用方式比较反人类. 库函数或者说SDK的作用本就应该是隔绝内部实现机制, 给开发者最小的学习成本和界面, 来实现最多的功能. 在我看来, 这种两段式的设计完全没有做到这一点. 为此, 我和很多人一样, 写了一个类来包装这个API调用, 类似下面这样:

type KMSSvc struct {
        Config aws.Config         // The AWS session info
        EncKey string             // The KMS key used to encrypt text
        Cli    kms.ClientAPI      // The client struct from kms module
}

写完这样的代码还不算结束, 对于这样的两段式调用, 单元测试起来也是麻烦. 本来mock一个对象或实例就可以做到的事情, 现在只能用下面这样的方式来做到:

// 对DescribeKey这个API定义一个struct, 方便测试
type mockDescribeKey struct {
        kmsiface.ClientAPI
        Resp  kms.DescribeKeyOutput
        Error error
}

func (m mockDescribeKey) DescribeKeyRequest(in *kms.DescribeKeyInput) kms.DescribeKeyRequest {
        return kms.DescribeKeyRequest{
                Request: &aws.Request{
                        Data:        &m.Resp,
                        HTTPRequest: &http.Request{},
                        Error:       m.Error,
                },
        }
}

而且, 为了完成测试, 你必须使用kmsiface.ClientAPI而不是正常的kms.ClientAPI:

type KMSSvc struct {
        Config aws.Config         // The AWS session info
        EncKey string             // The KMS key used to encrypt text
        Cli    kmsiface.ClientAPI // The client struct from kms module
}

后面, 正向和反向测试的示例代码如下:

func TestDescribeKeySuccess(test *testing.T) {
        somekey := kms.KeyMetadata{
                Arn: aws.String("somearn"),
        }
        kms_svc := psyml.KMSSvc{
                Cli: mockDescribeKey{
                        Resp: kms.DescribeKeyOutput{
                                KeyMetadata: &somekey,
                        },
                },
        }

        arn, _ := kms_svc.DescribeKey("somekeyid")

        assert.Equal(test, arn, "somearn", "describe key failed.")
}

func TestDescribeKeyFail404(test *testing.T) {
        kms_svc := psyml.KMSSvc{
                Cli: mockDescribeKey{Error: genErr("KeyDoesNotExist", 404)},
        }

        arn, err := kms_svc.DescribeKey("somekeyid")

        assert.Equal(test, "", arn, "should get empty arn when key does not exist")
        assert.Equal(test, err, psyml.PsYamlKMSNoKeyError, "should get proper error when key does not exist")
}

AWS GamesDay

昨天去参加了AWS Community Day. 主题演讲是Jeff-我的头发不再是紫色-Barr同学, 实话说, 挺无聊的, 我听得很犯困. 后面参加了GamesDay活动. 实质上, 这是一个培训活动, 其中, 你会在一个虚拟的场景下去完成一定的任务, 完成得越早, 完成得越多, 得分就会越高. 这次在墨尔本的活动里, 大主题是网络和VPC Endpoint, 首先是用Transit Gateway来简化VPC Peering, 然后是用Global Accelerator来加速多个区域的应用部署, 最后是一个网络连接调试场景. 这是我第一次参加这样的活动, 第一个任务的时候比较懵(之前工作接触这部分也是比较少), 后面到了Global Accelerator的部分就比较如鱼得水了. 可惜由于记分机制, 后面也没赶上前面的差距, 最后排名大概是70%. 不算差, 不过也不算太好. 总体感觉还挺不错, 遇到了一些老朋友, 交了一些新朋友.