diff --git "a/docs/02-CurveBS/03-test/ci\344\273\213\347\273\215.md" "b/docs/02-CurveBS/03-test/ci\344\273\213\347\273\215.md" new file mode 100644 index 0000000..9215353 --- /dev/null +++ "b/docs/02-CurveBS/03-test/ci\344\273\213\347\273\215.md" @@ -0,0 +1,188 @@ +# 概述 + +本文将主要介绍社区人员在参与curve项目开发过程中如何快速提交PR并进行CI测试,以及快速定位CI失败原因。 + +## 如何提交PR + +在完成代码编写后,就可以提交 PR。当然如果开发尚未完成,在某些情况下也可以先提交 PR,比如希望先让社区看一下大致的解决方案,可以在完成代码框架后提价 PR。 + +[Curve 编译环境快速构建](https://github.com/opencurve/curve/blob/master/docs/cn/build_and_run.md) + +[Curve 测试用例编译及执行](https://github.com/opencurve/curve/blob/master/docs/cn/build_and_run.md#测试用例编译及执行) + +对于 PR 我们有如下要求: + +- CURVE编码规范严格按照[Google C++开源项目编码指南](https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/contents/)来进行代码编写,请您也遵循这一指南来提交您的代码。 +- 代码必须有测试,文档除外,单元测试(增量行覆盖80%以上,增量分支覆盖70%以上);集成测试(与单元测试合并统计,满足单元测试覆盖率要求即可) +- 请尽可能详细的填写 PR 的描述,关联相关问题的 issuse,PR commit message 能清晰看出解决的问题。 +- CI 通过之后可开始进行 review,每个 PR 在合并之前都需要至少得到两个 Committer/Maintainer 的 LGTM。 +- PR 代码需要一定量的注释来使代码容易理解,且所有注释和 review 意见和回复均要求使用英语。 + +对于 commit message: + +一条好的 commit message 需要包含以下要素: + +1. What is your change?(必须) +2. Why this change was made?(必须) +3. What effect does the commit have? (可选) + +说明提交的 PR 做了那些修改:性能优化?修复bug?增加功能?以及这么做的原因。最后描述以下这样修改带来的影响,包括性能等等。当然对一些简单的修改,修改的原因和影响可以忽略。在 message中尽量遵循以下原则: + +- 总结说明 PR 的功能和作用 +- 使用短句和简单的动词 +- 避免长的复合词和缩写 + +在提交时请尽可能的遵循以下格式: + +``` +[type]: + +[body] + +[footer] +``` + +type 可以是以下类型之一: + +- build: 影响系统构建以及外部依赖 +- ci: 影响持续继承相关的功能 +- docs: 文档相关的修改 +- feat: 增加新的特性 +- fix: bug 修复 +- perf: 性能提升 +- refactor: 重构相关的代码,不增加功能也不修复错误 +- style: 不影响代码的的含义的修改,仅仅是修改代码风格 +- test: 单元测试相关的修改 + +第一行表示标题应尽可能保持 70 个字符以内,阐述修改的模块以及内容,多模块可以使用 `*` 来表示,并在正文阶段说明修改的模块。 + +footer 是可选的,用来记录对应因为这些更改而可以关闭的 issue,如 `Close #12345` + +## CI 测试过程 + +PR提交到 Curve master 分支后需要在comment中输入cicheck触发Curve CI,需保证 CI 通过,CI 的 Jenkins 用户名密码为 netease/netease,如遇到 CI 运行失败可以登录 Jenkins 平台查看失败原因。测试内容包括: + +1) cpplint静态检查 + +主要进行测试内容为: + +cpplint --linelength=80 --counting=detailed --output=junit --filter=-build/c++11 --quiet $( find . -name *.h -or -name *.cc -or -name *.cpp ) 2>&1 | tee cpplint-style.xml + +2) 单元测试 + +单元测试主要执行的就是仓库中:https://github.com/opencurve/curve/blob/master/ut.sh + +为提升测试效率,所有单元测试用例为并行执行,需要注意增加的单元测试里起的服务不能和其他用例里起的服务使用同一端口,否则会因为端口占用失败 + +测试结束后进行覆盖率的卡点校验,当前覆盖率配置为: + +``` +if [ $1 == "curvebs" ];then + +check_repo_branch_coverage 59 +check_repo_line_coverage 76 + +## two arguments are module and expected branch coverage ratio +check_module_branch_coverage "src/mds" 70 +check_module_branch_coverage "src/client" 78 +check_module_branch_coverage "src/chunkserver" 65 +check_module_branch_coverage "src/snapshotcloneserver" 65 +check_module_branch_coverage "src/tools" 65 +check_module_branch_coverage "src/common" 65 +check_module_branch_coverage "src/fs" 65 +check_module_branch_coverage "src/idgenerator" 79 +check_module_branch_coverage "src/kvstorageclient" 70 +check_module_branch_coverage "src/leader_election" 100 +check_module_branch_coverage "nebd" 75 + +elif [ $1 == "curvefs" ];then + +check_module_branch_coverage "mds" 59 +check_module_branch_coverage "client" 59 +check_module_branch_coverage "metaserver" 65 +check_module_branch_coverage "common" 16 +check_module_branch_coverage "tools" 0 +fi +``` + +测试结束后会输出覆盖率报告,例如: http://59.111.91.248:8080/job/curve_untest_job/6149/HTML_20Report/ + +如果测试失败,可以打开对应的curve_untest_job的控制台输出日志,直接页面拉到最后会打印出错误的原因,覆盖率不足会打印在最后,如果是单元测试用例失败,可以从下往上翻页,找到失败的地方,比如: + + + +``` +[ FAILED ] 1 test, listed below: +[ FAILED ] EtcdClientTest.GetEtcdClusterStatus + + 1 FAILED TEST +test bazel-bin/test/mds/server/mds-test.log log is --------------------------------------------->>>>>>>> +Running main() from gmock_main.cc +[==========] Running 1 test from 1 test case. +[----------] Global test environment set-up. +[----------] 1 test from MDSTest +[ RUN ] MDSTest.common +2022-12-07 18:02:48.753204 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:49.753500 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:50.753831 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:51.754211 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:52.755814 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:53.756543 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +test/mds/server/mds_test.cpp:76: Failure +Value of: initSuccess + Actual: false +Expected: true +``` + +3) pjdfstest测试 + +pjdfstest 主要是用来测试curvefs POSIX上的兼容性,会部署单机版的curvefs环境,然后进行pjdtest的执行,用的工具在 https://github.com/pjd/pjdfstest 。可以使用如下脚本进行自行测试: + +``` +#!/usr/bin/env bash + +set -e + +git clone https://github.com/pjd/pjdfstest.git +cd pjdfstest +autoreconf -ifs +./configure +make pjdfstest +cd .. +mkdir tmp +cd tmp +# must be root! +sudo prove -r -v --exec 'bash -x' ../pjd*/tests +cd .. +rm -rf tmp pjd* +``` + +如果测试失败,也需要进入控制台输出,拉到最后查看具体失败的原因 + +3) failover异常自动化 + +异常自动化会进行整体真实环境部署和io注入、故障测试,主要流程: + +主要流程: + + 初始化集群 → 用户io注入 (数据面) → 并发调用管理接口(管控面) → 触发异常 → sleep a time → 异常恢复(恢复校验) → 数据校验(ioerror、读写一致性、三副本一致性、抖动) → 管理接口校验 &资源回收等校验 + +测试完成后会输出整体的测试报告,具体测试过程和测试结果可以点击对应提交的curve_failover_job 下的log.html , 可以看到比较完整的测试流程、步骤、操作和结果输出,比如 [log.html](http://59.111.91.248:8080/job/curve_failover_job/2579/robot/report/log.html) + +## 常见问题 + +如何登录jenkins? + +由于内部的一些权限要求,需要用用户名密码登录jenkins ,开源社区的可以使用netease/netease 的账号/密码进行登录 + +如果再次触发失败pr的CI 构建? + +可以打开pr ,在最底部comment ''recheck" 字段,进行再次触发构建 + +如何过滤CI? + +对于一些文档修改或其他不影响代码流程的内容,我们可以不进行CI构建,可以在创建PR的时候在标题增加[skipci] 字段 + +触发构建后立刻返回了失败? + +查看一下失败的job内容,多数是因为测试任务在进行排队等待。如果job是waiting_in_line ,就是在排队 diff --git "a/docs/02-CurveBS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/docs/02-CurveBS/03-test/\346\265\213\350\257\225\345\267\245\345\205\267.md" similarity index 100% rename from "docs/02-CurveBS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225.md" rename to "docs/02-CurveBS/03-test/\346\265\213\350\257\225\345\267\245\345\205\267.md" diff --git "a/docs/02-CurveBS/03-test/\346\265\213\350\257\225\347\216\257\345\242\203\351\205\215\347\275\256\344\277\241\346\201\257.md" "b/docs/02-CurveBS/03-test/\346\265\213\350\257\225\347\216\257\345\242\203\351\205\215\347\275\256\344\277\241\346\201\257.md" new file mode 100644 index 0000000..ad16336 --- /dev/null +++ "b/docs/02-CurveBS/03-test/\346\265\213\350\257\225\347\216\257\345\242\203\351\205\215\347\275\256\344\277\241\346\201\257.md" @@ -0,0 +1,79 @@ +# Curve 测试环境配置信息 + +Curve 当前测试的性能,如果没有特别说明,都是在基于以下配置的机器上测试的。该配置仅仅表示curve当前性能数据的测试环境,由于部分硬件版本比较旧,该环境的硬件不作为推荐硬件型号,但是对硬件的配置部分可做参考。 + +## 集群topo + +### curvebs 块存储测试集群规模 + +mds和chunkserver服务混合部署。 + +mds : 3台机器 + +chunkserver : 9台机器 * 20块盘/每台机器 + +## 机器选型 + +| 计算/存储节点机型 | +| --- | +| Dell Inc. PowerEdge R730xd | +| Inspur NF5280M4 | + +## mds 节点 + +| 模块 | 版本 | 配置 | +| --- | --- | --- | +| 机型 | Dell PowerEdge R730xd | +| os | debain9 | +| 内核 | 4.9.65| +| cpu||设置performance,开启cpu性能最大化| +| 网卡| Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer2+3 (2)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 200
Down Delay (ms): 200 |万M网卡双网口组bond| +|系统盘||1.2T*2 SAS (RAID1模式)
初始化之后进行拷盘测试,提前发现并剔除坏盘、慢盘等异常| +|数据盘||1.8T*2 SSD (不需要RAID)
初始化之后进行拷盘测试,提前发现并剔除坏盘、慢盘等异常| + + +## chunkserver 节点 + +|模块|版本|配置| +|---|---|---| +|机型|inspur NF5280M4| | +|os|debian9| | +|内核|4.9.65| | +|cpu| |设置performance,开启cpu性能最大化| +|megaraid_sas| 06.811.02.00-rc4| | +|数据盘raid卡配置|1.RAID FW 版本:24.21.0-0061
2.RAID卡驱动版本:06.811.02.00-rc4|1. 配置为JBOD模式
2. RAID 卡关闭 consistent check
3.RAID卡缓存策略:WriteThrough| +|数据盘磁盘|数据盘类型:1.8TB * 20 Intel S4500
| 1.数据盘关闭磁盘缓存
2.磁盘调度策略,SSD盘noop,HDD盘deadline
// 初始化之后进行拷盘测试,提前发现并剔除坏盘、慢盘等异常
3、 sudo tune2fs -m 0 /dev/sda8
释放文件系统预留的5%空间
4、如果至少两个raid卡,每个raid卡上数据盘尽量均衡 | +| 网卡|bond配置(
Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer2+3 (2)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 200
Down Delay (ms): 200 )|万M网卡双网口组bond| +系统盘|1.2T*2 SAS | RAID1模式| +|fd数量||1.系统允许的最大fd数量至少为10000000
2.单个进程允许的最大fd数量不低于250000| +|mmap地址数量||每一个bthread都需要使用mmap分配stack,mmap数量操作系统是有限制的,建议修改/proc/sys/vm/max_map_count 至少为5642720。| + +## 一些相关的命令 + +### raid卡查询命令 + +1. RAID FW 版本 查询命令:`sudo /usr/sbin/megacli -AdpAllInfo -aALL | grep "FW Package Build"` +2. RAID 卡关闭 consistent check 查询命令:`sudo /usr/sbin/megacli -AdpCcSched -info -a0` +3. RAID卡缓存策略查询命令:`sudo megacli -LDGetProp -Cache -LALL -a0` +4. RAID卡驱动版本查询命令:`sudo modinfo megaraid_sas` + +### 磁盘相关命令 + +1. 关闭磁盘缓存命令:`sudo /sbin/hdparm -W 0 /dev/sdh` +2. 磁盘缓存是否关闭,查询命令:`sudo /sbin/hdparm -W /dev/sdh` +3. 磁盘调度策略,查询命令:`cat /sys/block/sdxxx/queue/schedule` +4. 释放文件系统预留空空间命令:`sudo tune2fs -m 0 /dev/sda8` + +### 修改单个进程的允许的最大fs数量 + +1. 查询系统允许的最大fd数量:`cat /proc/sys/fs/file-max` +2. 查询单个进程允许的最大fd数量:`ulimit -n` +3. 修改单个进程允许的最大fd数量: + +``` +修改/etc/sysctl.conf配置,然后执行sysctl -p 生效。 +echo "fs.nr_open = 2500000" >> /etc/sysctl.conf +echo "fs.file-max = 40000000" >> /etc/sysctl.conf +``` + + diff --git "a/docs/02-CurveBS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" "b/docs/02-CurveBS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" new file mode 100644 index 0000000..d9db498 --- /dev/null +++ "b/docs/02-CurveBS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" @@ -0,0 +1,234 @@ +# 编译环境搭建 + +**请注意:** + +1. 如您只是想体验Curve的部署流程和基本功能,**则不需要编译Curve**,请参考 [部署](https://github.com/opencurve/curveadm/wiki) +2. 本文档仅用来帮助你搭建Curve代码编译环境,便于您参与Curve的开发调试 +3. 以下镜像和编译过程目前仅支持 x86 系统 +4. 如要编译[arm分支](https://github.com/opencurve/curve/pull/2408),请根据 [Dockerfile](https://github.com/opencurve/curve/blob/master/docker/debian9/compile/Dockerfile)打包编译镜像 +5. 目前master分支不支持在arm系统上编译运行 +6. 推荐 debian 10及以上版本的操作系统,其他操作系统未经过全面测试 + +## 使用Docker进行编译(推荐方式) + +### 获取或者构建docker镜像 + +方法一:从docker hub镜像库中拉取docker镜像(推荐方式) + +```bash +docker pull opencurvedocker/curve-base:build-debian9 +``` + +方法二:手动构建docker镜像 + +使用工程目录下的 docker/debian9/compile/Dockerfile 进行构建,命令如下: + +```bash +docker build -t opencurvedocker/curve-base:build-debian9 +``` + +**注意:** 上述操作不建议在Curve工程目录执行,否则构建镜像时会把当前目录的文件都复制到docker镜像中,建议把Dockerfile拷贝到新建的干净目录下进行docker镜像的构建。 + +### 在docker镜像中编译 + +```bash +git clone https://github.com/opencurve/curve.git 或者 git clone https://gitee.com/mirrors/curve.git +cd curve +# 如果你想在容器内完成编译+制作+上传镜像的操作,可以添加以下参数 +# -v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker +# --rm 会在容器退出后自动删除容器,如果你想保留容器,可以去掉该参数 +docker run --rm -v $(pwd):/curve -w /curve -v ${HOME}/.cache:${HOME}/.cache -v ${HOME}/go:${HOME}/go --user $(id -u ${USER}):$(id -g ${USER}) -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro --privileged -it opencurvedocker/curve-base:build-debian9 bash +# (中国大陆可选)将外部依赖替换为国内下载点或镜像仓库,可以加快编译速度: bash replace-curve-repo.sh + +# curve v2.0 之前 +bash mk-tar.sh (编译 curvebs 并打tar包) +bash mk-deb.sh (编译 curvebs 并打debian包) + +# (当前)curve v2.0 及之后 +# 编译 curvebs: +make build stor=bs dep=1 +# or +make dep stor=bs && make build stor=bs +# 编译 curvefs: +make build stor=fs dep=1 +# or +make dep stor=fs && make build stor=fs +``` + +**注意:** `mk-tar.sh` 和 `mk-deb.sh` 用于 curve v2.0 之前版本的编译打包,v2.0 版本之后不再维护。 + +## 在物理机上编译 + +Curve编译依赖的包括: + +| 依赖 | 版本 | +|:-- |:-- | +| bazel | 4.2.2 | +| gcc | 支持c++11的兼容版本 | + +Curve的其他依赖项,均由bazel去管理,不可单独安装。 + +**注意:** 4.* 版本的 bazel 均可以成功编译 Curve 项目,其他版本不兼容。 +4.2.2 为推荐版本。 + +### 安装依赖 + +编译相关的软件依赖可以参考 [dockerfile](../../docker/debian9/compile/Dockerfile) 中的安装步骤。 + +### 一键编译 + +```bash +git clone https://github.com/opencurve/curve.git 或者 git clone https://gitee.com/mirrors/curve.git +# (中国大陆可选)将外部依赖替换为国内下载点或镜像仓库,可以加快下载速度: bash replace-curve-repo.sh +# curve v2.0 之前 +bash mk-tar.sh (编译 curvebs 并打tar包) +bash mk-deb.sh (编译 curvebs 并打debian包) + +# (当前)curve v2.0 及之后 +# 编译 curvebs: +make build stor=bs dep=1 +# or +make dep stor=bs && make build stor=bs +# 编译 curvefs: +make build stor=fs dep=1 +# or +make dep stor=fs && make build stor=fs +``` +### 制作镜像 + +该步骤可以在容器内执行也可以在物理机上执行。 +注意若是在容器内执行,需要在执行 `docker run` 命令时添加 `-v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker` 参数。 + +```bash +# 编译 curvebs: +# 后面的tag参数可以自定义,用于上传到镜像仓库 +make image stor=bs tag=test +# 编译 curvefs: +make image stor=fs tag=test +``` + +### 上传镜像 + +```bash +# test 为上一步中的tag参数 +docker push test +``` + +## 测试用例编译及执行 + +### 编译全部模块 + +仅编译全部模块,不进行打包 +```bash +bash ./build.sh +``` + +### 列出所有测试模块 + +```bash +# curvebs +bazel query '//test/...' +# curvefs +bazel query '//curvefs/test/...' +``` + +### 编译对应模块的代码 + +编译对应模块,例如test/common目录下的common-test测试: + +```bash +bazel build test/common:common-test --copt -DHAVE_ZLIB=1 --define=with_glog=true --compilation_mode=dbg --define=libunwind=true +``` + +### 执行测试 + +执行测试前需要先准备好测试用例运行所需的依赖: + +运行单元测试: +- 构建对应的模块测试: + ```bash + $ bazel build xxx/...//:xxx_test + ``` +- 运行对应的模块测试: + ```bash + $ bazel run xxx/...//:xxx_test + # 或者 + $ ./bazel-bin/xxx/.../xxx_test + ``` +- 编译全部测试及文件 + ```bash + $ bazel build "..." + ``` +- bazel 默认自带缓存编译, 但有时可能会失效. + + 清除项目构建缓存: + ```bash + $ bazel clean + ``` + + 清除项目依赖缓存(bazel 会将WORKSPACE 文件中的指定依赖项自行编译, 这部分同样也会缓存): + ```bash + $ bazel clean --expunge + ``` +- debug 模式编译(-c 指定向bazel 传递参数), 该模式会在默认构建文件中加入调试符号, 及减少优化等级. + ```bash + $ bazel build xxx//:xxx_test -c dbg + ``` +- 优化模式编译 + ```bash + $ bazel build xxx//:xxx_test -c opt + # 优化模式下加入调试符号 + $ bazel build xxx//:xxx_test -c opt --copt -g + ``` +- 更多文档, 详见 [bazel docs](https://bazel.build/docs). + +#### 动态库 + +```bash +export LD_LIBRARY_PATH=/thirdparties/etcdclient:/thirdparties/aws-sdk/usr/lib:/usr/local/lib:${LD_LIBRARY_PATH} +``` + +#### fake-s3 + +快照克隆集成测试中,使用了开源的[fake-s3](https://github.com/jubos/fake-s3)模拟真实的s3服务。 + +```bash +$ apt install ruby -y OR yum install ruby -y +$ gem install fakes3 +$ fakes3 -r /S3_DATA_DIR -p 9999 --license YOUR_LICENSE_KEY +``` + +备注: + +- `-r S3_DATA_DIR`:存放数据的目录 +- `--license YOUR_LICENSE_KEY`:fakes3需要key才能运行,申请地址见[fake-s3](https://github.com/jubos/fake-s3) +- `-p 9999`:fake-s3服务启动的端口,**不用更改** + +#### etcd + +```bash +wget -ct0 https://github.com/etcd-io/etcd/releases/download/v3.4.10/etcd-v3.4.10-linux-amd64.tar.gz +tar zxvf etcd-v3.4.10-linux-amd64.tar.gz +cd etcd-v3.4.10-linux-amd64 && cp etcd etcdctl /usr/bin +``` + +#### 执行单个测试模块 + +```bash +./bazel-bin/test/common/common-test +``` + +#### 运行单元/集成测试 + +bazel 编译后的可执行程序都在 `./bazel-bin` 目录下,例如 test/common 目录下的测试代码对应的测试程序为 `./bazel-bin/test/common/common-test`,可以直接运行程序进行测试。 +- CurveBS相关单元测试程序目录在 ./bazel-bin/test 目录下 +- CurveFS相关单元测试程序目录在 ./bazel-bin/curvefs/test 目录下 +- 集成测试在 ./bazel-bin/test/integration 目录下 +- NEBD相关单元测试程序在 ./bazel-bin/nebd/test 目录下 +- NBD相关单元测试程序在 ./bazel-bin/nbd/test 目录下 + +如果想运行所有的单元测试和集成测试,可以执行工程目录下的ut.sh脚本: + +```bash +bash ut.sh +``` diff --git "a/docs/03-CurveFS/03-test/ci\344\273\213\347\273\215.md" "b/docs/03-CurveFS/03-test/ci\344\273\213\347\273\215.md" new file mode 100644 index 0000000..9215353 --- /dev/null +++ "b/docs/03-CurveFS/03-test/ci\344\273\213\347\273\215.md" @@ -0,0 +1,188 @@ +# 概述 + +本文将主要介绍社区人员在参与curve项目开发过程中如何快速提交PR并进行CI测试,以及快速定位CI失败原因。 + +## 如何提交PR + +在完成代码编写后,就可以提交 PR。当然如果开发尚未完成,在某些情况下也可以先提交 PR,比如希望先让社区看一下大致的解决方案,可以在完成代码框架后提价 PR。 + +[Curve 编译环境快速构建](https://github.com/opencurve/curve/blob/master/docs/cn/build_and_run.md) + +[Curve 测试用例编译及执行](https://github.com/opencurve/curve/blob/master/docs/cn/build_and_run.md#测试用例编译及执行) + +对于 PR 我们有如下要求: + +- CURVE编码规范严格按照[Google C++开源项目编码指南](https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/contents/)来进行代码编写,请您也遵循这一指南来提交您的代码。 +- 代码必须有测试,文档除外,单元测试(增量行覆盖80%以上,增量分支覆盖70%以上);集成测试(与单元测试合并统计,满足单元测试覆盖率要求即可) +- 请尽可能详细的填写 PR 的描述,关联相关问题的 issuse,PR commit message 能清晰看出解决的问题。 +- CI 通过之后可开始进行 review,每个 PR 在合并之前都需要至少得到两个 Committer/Maintainer 的 LGTM。 +- PR 代码需要一定量的注释来使代码容易理解,且所有注释和 review 意见和回复均要求使用英语。 + +对于 commit message: + +一条好的 commit message 需要包含以下要素: + +1. What is your change?(必须) +2. Why this change was made?(必须) +3. What effect does the commit have? (可选) + +说明提交的 PR 做了那些修改:性能优化?修复bug?增加功能?以及这么做的原因。最后描述以下这样修改带来的影响,包括性能等等。当然对一些简单的修改,修改的原因和影响可以忽略。在 message中尽量遵循以下原则: + +- 总结说明 PR 的功能和作用 +- 使用短句和简单的动词 +- 避免长的复合词和缩写 + +在提交时请尽可能的遵循以下格式: + +``` +[type]: + +[body] + +[footer] +``` + +type 可以是以下类型之一: + +- build: 影响系统构建以及外部依赖 +- ci: 影响持续继承相关的功能 +- docs: 文档相关的修改 +- feat: 增加新的特性 +- fix: bug 修复 +- perf: 性能提升 +- refactor: 重构相关的代码,不增加功能也不修复错误 +- style: 不影响代码的的含义的修改,仅仅是修改代码风格 +- test: 单元测试相关的修改 + +第一行表示标题应尽可能保持 70 个字符以内,阐述修改的模块以及内容,多模块可以使用 `*` 来表示,并在正文阶段说明修改的模块。 + +footer 是可选的,用来记录对应因为这些更改而可以关闭的 issue,如 `Close #12345` + +## CI 测试过程 + +PR提交到 Curve master 分支后需要在comment中输入cicheck触发Curve CI,需保证 CI 通过,CI 的 Jenkins 用户名密码为 netease/netease,如遇到 CI 运行失败可以登录 Jenkins 平台查看失败原因。测试内容包括: + +1) cpplint静态检查 + +主要进行测试内容为: + +cpplint --linelength=80 --counting=detailed --output=junit --filter=-build/c++11 --quiet $( find . -name *.h -or -name *.cc -or -name *.cpp ) 2>&1 | tee cpplint-style.xml + +2) 单元测试 + +单元测试主要执行的就是仓库中:https://github.com/opencurve/curve/blob/master/ut.sh + +为提升测试效率,所有单元测试用例为并行执行,需要注意增加的单元测试里起的服务不能和其他用例里起的服务使用同一端口,否则会因为端口占用失败 + +测试结束后进行覆盖率的卡点校验,当前覆盖率配置为: + +``` +if [ $1 == "curvebs" ];then + +check_repo_branch_coverage 59 +check_repo_line_coverage 76 + +## two arguments are module and expected branch coverage ratio +check_module_branch_coverage "src/mds" 70 +check_module_branch_coverage "src/client" 78 +check_module_branch_coverage "src/chunkserver" 65 +check_module_branch_coverage "src/snapshotcloneserver" 65 +check_module_branch_coverage "src/tools" 65 +check_module_branch_coverage "src/common" 65 +check_module_branch_coverage "src/fs" 65 +check_module_branch_coverage "src/idgenerator" 79 +check_module_branch_coverage "src/kvstorageclient" 70 +check_module_branch_coverage "src/leader_election" 100 +check_module_branch_coverage "nebd" 75 + +elif [ $1 == "curvefs" ];then + +check_module_branch_coverage "mds" 59 +check_module_branch_coverage "client" 59 +check_module_branch_coverage "metaserver" 65 +check_module_branch_coverage "common" 16 +check_module_branch_coverage "tools" 0 +fi +``` + +测试结束后会输出覆盖率报告,例如: http://59.111.91.248:8080/job/curve_untest_job/6149/HTML_20Report/ + +如果测试失败,可以打开对应的curve_untest_job的控制台输出日志,直接页面拉到最后会打印出错误的原因,覆盖率不足会打印在最后,如果是单元测试用例失败,可以从下往上翻页,找到失败的地方,比如: + + + +``` +[ FAILED ] 1 test, listed below: +[ FAILED ] EtcdClientTest.GetEtcdClusterStatus + + 1 FAILED TEST +test bazel-bin/test/mds/server/mds-test.log log is --------------------------------------------->>>>>>>> +Running main() from gmock_main.cc +[==========] Running 1 test from 1 test case. +[----------] Global test environment set-up. +[----------] 1 test from MDSTest +[ RUN ] MDSTest.common +2022-12-07 18:02:48.753204 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:49.753500 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:50.753831 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:51.754211 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:52.755814 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +2022-12-07 18:02:53.756543 I | etcd do NewCient get err:context deadline exceeded, errCode:DeadlineExceeded +test/mds/server/mds_test.cpp:76: Failure +Value of: initSuccess + Actual: false +Expected: true +``` + +3) pjdfstest测试 + +pjdfstest 主要是用来测试curvefs POSIX上的兼容性,会部署单机版的curvefs环境,然后进行pjdtest的执行,用的工具在 https://github.com/pjd/pjdfstest 。可以使用如下脚本进行自行测试: + +``` +#!/usr/bin/env bash + +set -e + +git clone https://github.com/pjd/pjdfstest.git +cd pjdfstest +autoreconf -ifs +./configure +make pjdfstest +cd .. +mkdir tmp +cd tmp +# must be root! +sudo prove -r -v --exec 'bash -x' ../pjd*/tests +cd .. +rm -rf tmp pjd* +``` + +如果测试失败,也需要进入控制台输出,拉到最后查看具体失败的原因 + +3) failover异常自动化 + +异常自动化会进行整体真实环境部署和io注入、故障测试,主要流程: + +主要流程: + + 初始化集群 → 用户io注入 (数据面) → 并发调用管理接口(管控面) → 触发异常 → sleep a time → 异常恢复(恢复校验) → 数据校验(ioerror、读写一致性、三副本一致性、抖动) → 管理接口校验 &资源回收等校验 + +测试完成后会输出整体的测试报告,具体测试过程和测试结果可以点击对应提交的curve_failover_job 下的log.html , 可以看到比较完整的测试流程、步骤、操作和结果输出,比如 [log.html](http://59.111.91.248:8080/job/curve_failover_job/2579/robot/report/log.html) + +## 常见问题 + +如何登录jenkins? + +由于内部的一些权限要求,需要用用户名密码登录jenkins ,开源社区的可以使用netease/netease 的账号/密码进行登录 + +如果再次触发失败pr的CI 构建? + +可以打开pr ,在最底部comment ''recheck" 字段,进行再次触发构建 + +如何过滤CI? + +对于一些文档修改或其他不影响代码流程的内容,我们可以不进行CI构建,可以在创建PR的时候在标题增加[skipci] 字段 + +触发构建后立刻返回了失败? + +查看一下失败的job内容,多数是因为测试任务在进行排队等待。如果job是waiting_in_line ,就是在排队 diff --git "a/docs/03-CurveFS/03-test/curvefs2.4\347\211\210\346\234\254\346\265\213\350\257\225\346\212\245\345\221\212.pdf" "b/docs/03-CurveFS/03-test/curvefs2.4\347\211\210\346\234\254\346\265\213\350\257\225\346\212\245\345\221\212.pdf" new file mode 100644 index 0000000..f2d5800 Binary files /dev/null and "b/docs/03-CurveFS/03-test/curvefs2.4\347\211\210\346\234\254\346\265\213\350\257\225\346\212\245\345\221\212.pdf" differ diff --git "a/docs/03-CurveFS/03-test/\345\274\202\345\270\270\350\207\252\345\212\250\345\214\226\346\226\271\346\263\225.md" "b/docs/03-CurveFS/03-test/\345\274\202\345\270\270\350\207\252\345\212\250\345\214\226\346\226\271\346\263\225.md" new file mode 100644 index 0000000..45d42a6 --- /dev/null +++ "b/docs/03-CurveFS/03-test/\345\274\202\345\270\270\350\207\252\345\212\250\345\214\226\346\226\271\346\263\225.md" @@ -0,0 +1,26 @@ +#异常测试方法 +##测试目的 +- Curve是网易云存储产品组推出的新一代分布式存储平台,致力于打造一个支持块、对象、文件等存储形态的统一平台。本次测试对象主要为支持块设备功能。 + +- 生产环境中,故障是一种常态,测试环境中需要尽可能的模拟生产环境中的故障,以此来评估系统的可用性、一致性等。 + +##测试方法 +- 异常测试的环境部署要求尽可能与真实环境一致,当前测试环境定义为6台chunkserver节点,1台mds节点(尚无failover),2台client节点,测试场景尽可能模拟用户使用的方式,读写io由云主机内部下发,管理接口直接采用openstack的接口。 + +- 异常项主要通过人为注入的方式触发,有些异常为真实的异常,例如机器宕机、拔网线等;有些异常通过软件模拟的方式,如磁盘io卡顿、服务异常等;有些异常则是在代码侧注入,该部分异常测试主要在集成测试中,不在这里讨论。 + +- 异常测试主要校验真实用户场景中,在异常触发情况下的系统行为,按影响面可以分为:用户无感知、影响管理面基本功能、引起性能衰减、引起io抖动、系统不可服务但可恢复、数据异常(ioerror、不一致、丢失)、系统无法恢复。 + + + +- 借鉴混沌工程的理论,测试用例设计的时候也会尽量符合下面原则,当然我们目前只是在测试环境批跑,条件允许的情况下,可以在beta云环境批跑,直到稳定后,可以去A级环境批跑。 + +- 建立稳定状态的假设; +- 多样化现实世界事件; +- 在生产环境运行实验; +- 持续自动化运行实验; +- 最小化“爆炸半径”。 +##测试用例 + - 一个最基本的异常测试用例格式如下: + + - 初始化集群 → 用户io注入 → 并发调用管理接口 → 触发异常 → sleep a random time → 异常恢复(恢复校验) → 数据校验(ioerror、读写一致性、三副本一致性、抖动) → 管理接口校验 → 资源回收校验 diff --git "a/docs/03-CurveFS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/docs/03-CurveFS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225\345\267\245\345\205\267.md" similarity index 100% rename from "docs/03-CurveFS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225.md" rename to "docs/03-CurveFS/03-test/\346\200\247\350\203\275\346\265\213\350\257\225\345\267\245\345\205\267.md" diff --git "a/docs/03-CurveFS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" "b/docs/03-CurveFS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" new file mode 100644 index 0000000..d9db498 --- /dev/null +++ "b/docs/03-CurveFS/03-test/\347\274\226\350\257\221\345\222\214\345\215\225\345\205\203\346\265\213\350\257\225.md" @@ -0,0 +1,234 @@ +# 编译环境搭建 + +**请注意:** + +1. 如您只是想体验Curve的部署流程和基本功能,**则不需要编译Curve**,请参考 [部署](https://github.com/opencurve/curveadm/wiki) +2. 本文档仅用来帮助你搭建Curve代码编译环境,便于您参与Curve的开发调试 +3. 以下镜像和编译过程目前仅支持 x86 系统 +4. 如要编译[arm分支](https://github.com/opencurve/curve/pull/2408),请根据 [Dockerfile](https://github.com/opencurve/curve/blob/master/docker/debian9/compile/Dockerfile)打包编译镜像 +5. 目前master分支不支持在arm系统上编译运行 +6. 推荐 debian 10及以上版本的操作系统,其他操作系统未经过全面测试 + +## 使用Docker进行编译(推荐方式) + +### 获取或者构建docker镜像 + +方法一:从docker hub镜像库中拉取docker镜像(推荐方式) + +```bash +docker pull opencurvedocker/curve-base:build-debian9 +``` + +方法二:手动构建docker镜像 + +使用工程目录下的 docker/debian9/compile/Dockerfile 进行构建,命令如下: + +```bash +docker build -t opencurvedocker/curve-base:build-debian9 +``` + +**注意:** 上述操作不建议在Curve工程目录执行,否则构建镜像时会把当前目录的文件都复制到docker镜像中,建议把Dockerfile拷贝到新建的干净目录下进行docker镜像的构建。 + +### 在docker镜像中编译 + +```bash +git clone https://github.com/opencurve/curve.git 或者 git clone https://gitee.com/mirrors/curve.git +cd curve +# 如果你想在容器内完成编译+制作+上传镜像的操作,可以添加以下参数 +# -v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker +# --rm 会在容器退出后自动删除容器,如果你想保留容器,可以去掉该参数 +docker run --rm -v $(pwd):/curve -w /curve -v ${HOME}/.cache:${HOME}/.cache -v ${HOME}/go:${HOME}/go --user $(id -u ${USER}):$(id -g ${USER}) -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro --privileged -it opencurvedocker/curve-base:build-debian9 bash +# (中国大陆可选)将外部依赖替换为国内下载点或镜像仓库,可以加快编译速度: bash replace-curve-repo.sh + +# curve v2.0 之前 +bash mk-tar.sh (编译 curvebs 并打tar包) +bash mk-deb.sh (编译 curvebs 并打debian包) + +# (当前)curve v2.0 及之后 +# 编译 curvebs: +make build stor=bs dep=1 +# or +make dep stor=bs && make build stor=bs +# 编译 curvefs: +make build stor=fs dep=1 +# or +make dep stor=fs && make build stor=fs +``` + +**注意:** `mk-tar.sh` 和 `mk-deb.sh` 用于 curve v2.0 之前版本的编译打包,v2.0 版本之后不再维护。 + +## 在物理机上编译 + +Curve编译依赖的包括: + +| 依赖 | 版本 | +|:-- |:-- | +| bazel | 4.2.2 | +| gcc | 支持c++11的兼容版本 | + +Curve的其他依赖项,均由bazel去管理,不可单独安装。 + +**注意:** 4.* 版本的 bazel 均可以成功编译 Curve 项目,其他版本不兼容。 +4.2.2 为推荐版本。 + +### 安装依赖 + +编译相关的软件依赖可以参考 [dockerfile](../../docker/debian9/compile/Dockerfile) 中的安装步骤。 + +### 一键编译 + +```bash +git clone https://github.com/opencurve/curve.git 或者 git clone https://gitee.com/mirrors/curve.git +# (中国大陆可选)将外部依赖替换为国内下载点或镜像仓库,可以加快下载速度: bash replace-curve-repo.sh +# curve v2.0 之前 +bash mk-tar.sh (编译 curvebs 并打tar包) +bash mk-deb.sh (编译 curvebs 并打debian包) + +# (当前)curve v2.0 及之后 +# 编译 curvebs: +make build stor=bs dep=1 +# or +make dep stor=bs && make build stor=bs +# 编译 curvefs: +make build stor=fs dep=1 +# or +make dep stor=fs && make build stor=fs +``` +### 制作镜像 + +该步骤可以在容器内执行也可以在物理机上执行。 +注意若是在容器内执行,需要在执行 `docker run` 命令时添加 `-v /var/run/docker.sock:/var/run/docker.sock -v /root/.docker:/root/.docker` 参数。 + +```bash +# 编译 curvebs: +# 后面的tag参数可以自定义,用于上传到镜像仓库 +make image stor=bs tag=test +# 编译 curvefs: +make image stor=fs tag=test +``` + +### 上传镜像 + +```bash +# test 为上一步中的tag参数 +docker push test +``` + +## 测试用例编译及执行 + +### 编译全部模块 + +仅编译全部模块,不进行打包 +```bash +bash ./build.sh +``` + +### 列出所有测试模块 + +```bash +# curvebs +bazel query '//test/...' +# curvefs +bazel query '//curvefs/test/...' +``` + +### 编译对应模块的代码 + +编译对应模块,例如test/common目录下的common-test测试: + +```bash +bazel build test/common:common-test --copt -DHAVE_ZLIB=1 --define=with_glog=true --compilation_mode=dbg --define=libunwind=true +``` + +### 执行测试 + +执行测试前需要先准备好测试用例运行所需的依赖: + +运行单元测试: +- 构建对应的模块测试: + ```bash + $ bazel build xxx/...//:xxx_test + ``` +- 运行对应的模块测试: + ```bash + $ bazel run xxx/...//:xxx_test + # 或者 + $ ./bazel-bin/xxx/.../xxx_test + ``` +- 编译全部测试及文件 + ```bash + $ bazel build "..." + ``` +- bazel 默认自带缓存编译, 但有时可能会失效. + + 清除项目构建缓存: + ```bash + $ bazel clean + ``` + + 清除项目依赖缓存(bazel 会将WORKSPACE 文件中的指定依赖项自行编译, 这部分同样也会缓存): + ```bash + $ bazel clean --expunge + ``` +- debug 模式编译(-c 指定向bazel 传递参数), 该模式会在默认构建文件中加入调试符号, 及减少优化等级. + ```bash + $ bazel build xxx//:xxx_test -c dbg + ``` +- 优化模式编译 + ```bash + $ bazel build xxx//:xxx_test -c opt + # 优化模式下加入调试符号 + $ bazel build xxx//:xxx_test -c opt --copt -g + ``` +- 更多文档, 详见 [bazel docs](https://bazel.build/docs). + +#### 动态库 + +```bash +export LD_LIBRARY_PATH=/thirdparties/etcdclient:/thirdparties/aws-sdk/usr/lib:/usr/local/lib:${LD_LIBRARY_PATH} +``` + +#### fake-s3 + +快照克隆集成测试中,使用了开源的[fake-s3](https://github.com/jubos/fake-s3)模拟真实的s3服务。 + +```bash +$ apt install ruby -y OR yum install ruby -y +$ gem install fakes3 +$ fakes3 -r /S3_DATA_DIR -p 9999 --license YOUR_LICENSE_KEY +``` + +备注: + +- `-r S3_DATA_DIR`:存放数据的目录 +- `--license YOUR_LICENSE_KEY`:fakes3需要key才能运行,申请地址见[fake-s3](https://github.com/jubos/fake-s3) +- `-p 9999`:fake-s3服务启动的端口,**不用更改** + +#### etcd + +```bash +wget -ct0 https://github.com/etcd-io/etcd/releases/download/v3.4.10/etcd-v3.4.10-linux-amd64.tar.gz +tar zxvf etcd-v3.4.10-linux-amd64.tar.gz +cd etcd-v3.4.10-linux-amd64 && cp etcd etcdctl /usr/bin +``` + +#### 执行单个测试模块 + +```bash +./bazel-bin/test/common/common-test +``` + +#### 运行单元/集成测试 + +bazel 编译后的可执行程序都在 `./bazel-bin` 目录下,例如 test/common 目录下的测试代码对应的测试程序为 `./bazel-bin/test/common/common-test`,可以直接运行程序进行测试。 +- CurveBS相关单元测试程序目录在 ./bazel-bin/test 目录下 +- CurveFS相关单元测试程序目录在 ./bazel-bin/curvefs/test 目录下 +- 集成测试在 ./bazel-bin/test/integration 目录下 +- NEBD相关单元测试程序在 ./bazel-bin/nebd/test 目录下 +- NBD相关单元测试程序在 ./bazel-bin/nbd/test 目录下 + +如果想运行所有的单元测试和集成测试,可以执行工程目录下的ut.sh脚本: + +```bash +bash ut.sh +```