test(etcdraft): add unit test for etcdraft package

This commit is contained in:
Lizen0512 2021-02-04 15:22:02 +08:00
parent ccb315510d
commit 8f361682ce
8 changed files with 476 additions and 253 deletions

19
go.sum
View File

@ -122,6 +122,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f h1:BOaYiTvg8p9vBUXpklC22XSK/mifLF7lG9jtmYYi3Tc=
github.com/davidlazar/go-crypto v0.0.0-20190912175916-7055855a373f/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
@ -142,6 +143,7 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
@ -152,6 +154,7 @@ github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc h1:jtW8jbpkO4YirRSyepBOH8E+2HEw6/hKkBvFPwhUN8c=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
@ -163,6 +166,7 @@ github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
@ -279,6 +283,7 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e h1:0aewS5NTyxftZHSnFaJmWE5oCCrj4DyEXkAiMa1iZJM=
github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
github.com/holiman/uint256 v1.1.1 h1:4JywC80b+/hSfljFlEBLHrrh+CIONLDz9NuFl0af4Mw=
github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -369,6 +374,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
@ -598,13 +604,14 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956 h1:f1CXhJSLo/JuTXLjv5PRtvLvzq7mxzD58Aet27k5QlU=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210112105719-497a79914e4e h1:gQf9QgAiiLrCInvcBBGvOU/6D8x6+kaJwHGXUlV8RTA=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210112105719-497a79914e4e/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956 h1:f1CXhJSLo/JuTXLjv5PRtvLvzq7mxzD58Aet27k5QlU=
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
github.com/meshplus/bitxhub-kit v1.0.0-rc1/go.mod h1:ra/AhOkPvpElI+wXrB9G6DjdcrdxFU3vMwA5MYKr9D0=
github.com/meshplus/bitxhub-kit v1.0.0/go.mod h1:7cWyhXWZfrQ3+EaxkRoXfuiG3Y5R9DXYJomeZKkETW8=
github.com/meshplus/bitxhub-kit v1.1.1 h1:vkPO88oA3+Kpc0N8lIgfj/U52KBuI+633hPbMYt1xm8=
@ -708,6 +715,7 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk=
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -731,9 +739,11 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw=
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
@ -777,6 +787,7 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@ -834,6 +845,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
@ -871,6 +883,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
@ -891,6 +904,7 @@ github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
@ -1141,6 +1155,7 @@ gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVY
gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -40,7 +40,7 @@ type Node struct {
batchTimerMgr *BatchTimer
proposeC chan *raftproto.RequestBatch // proposed ready, input channel
confChangeC <-chan raftpb.ConfChange // proposed cluster config changes
confChangeC chan raftpb.ConfChange // proposed cluster config changes
commitC chan *pb.CommitEvent // the hash commit channel
errorC chan<- error // errors from raft session
tickTimeout time.Duration // tick timeout
@ -361,7 +361,7 @@ func (n *Node) run() {
// 1: Write HardState, Entries, and Snapshot to persistent storage if they
// are not empty.
if err := n.raftStorage.Store(rd.Entries, rd.HardState, rd.Snapshot); err != nil {
n.logger.Errorf("failed to persist etcd/raft data: %s", err)
n.logger.Errorf("Failed to persist etcd/raft data: %s", err)
}
if !raft.IsEmptySnap(rd.Snapshot) {

View File

@ -5,32 +5,22 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/coreos/etcd/raft/raftpb"
"github.com/golang/mock/gomock"
crypto2 "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/crypto/asym"
"github.com/meshplus/bitxhub-kit/crypto/asym/ecdsa"
"github.com/meshplus/bitxhub-kit/log"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
"github.com/meshplus/bitxhub/internal/model/events"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/order"
"github.com/meshplus/bitxhub/pkg/peermgr"
"github.com/meshplus/bitxhub/pkg/peermgr/mock_peermgr"
libp2pcert "github.com/meshplus/go-libp2p-cert"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const to = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
func TestNode_Start(t *testing.T) {
repoRoot, err := ioutil.TempDir("", "node")
assert.Nil(t, err)
@ -200,159 +190,53 @@ func TestMulti_Node_Start_Without_Cert_Verification(t *testing.T) {
}
}
func listen(t *testing.T, order order.Order, swarm *peermgr.Swarm) {
orderMsgCh := make(chan events.OrderMessageEvent)
sub := swarm.SubscribeOrderMessage(orderMsgCh)
defer sub.Unsubscribe()
for {
select {
case ev := <-orderMsgCh:
err := order.Step(ev.Data)
require.Nil(t, err)
func TestReportState(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
err := node.Start()
ast.Nil(err)
blockHash := &types.Hash{
RawHash: [types.HashLength]byte{0},
}
txHashList := make([]*types.Hash, 0)
txHash := &types.Hash{
RawHash: [types.HashLength]byte{0},
}
txHashList = append(txHashList, txHash)
node.blockAppliedIndex.Store(uint64(10), uint64(10))
node.ReportState(uint64(10), blockHash, txHashList)
appliedIndex, ok := node.blockAppliedIndex.Load(uint64(10))
ast.Equal(true, ok)
ast.Equal(uint64(10), appliedIndex.(uint64))
nonce := node.GetPendingNonceByAccount("account1")
ast.Equal(uint64(1), nonce)
err = node.DelNode(uint64(1))
}
func generateTx() *pb.Transaction {
privKey, _ := asym.GenerateKeyPair(crypto.Secp256k1)
from, _ := privKey.PublicKey().Address()
tx := &pb.Transaction{
From: from,
To: types.NewAddressByStr(to),
Timestamp: time.Now().UnixNano(),
Nonce: 1,
}
_ = tx.Sign(privKey)
tx.TransactionHash = tx.Hash()
return tx
func TestGetPendingNonceByAccount(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
err := node.Start()
ast.Nil(err)
nonce := node.GetPendingNonceByAccount("account1")
ast.Equal(uint64(1), nonce)
err = node.DelNode(uint64(1))
}
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
m := make([]*repo.NetworkNodes, 0, len(addrs))
for i, addr := range addrs {
m = append(m, &repo.NetworkNodes{
ID: uint64(i + 1),
Account: "",
Pid: ids[i],
Hosts: []string{addr},
})
}
return m
}
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
var nodeKeys []crypto2.PrivKey
var privKeys []crypto.PrivateKey
var peers []string
var ids []string
port := 5001
for i := 0; i < peerCnt; i++ {
key, err := asym.GenerateKeyPair(crypto.ECDSA_P256)
require.Nil(t, err)
libp2pKey, err := convertToLibp2pPrivKey(key)
require.Nil(t, err)
nodeKeys = append(nodeKeys, libp2pKey)
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
require.Nil(t, err)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
peers = append(peers, peer)
ids = append(ids, id.String())
port++
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
require.Nil(t, err)
privKeys = append(privKeys, privKey)
}
return nodeKeys, privKeys, peers, ids
}
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
ecdsaPrivKey, ok := privateKey.(*ecdsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("convert to libp2p private key: not ecdsa private key")
}
libp2pPrivKey, _, err := crypto2.ECDSAKeyPairFromKey(ecdsaPrivKey.K)
if err != nil {
return nil, err
}
return libp2pPrivKey, nil
}
func newSwarms(t *testing.T, peerCnt int, certVerify bool) ([]*peermgr.Swarm, map[uint64]*pb.VpInfo) {
var swarms []*peermgr.Swarm
nodes := make(map[uint64]*pb.VpInfo)
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
mockCtl := gomock.NewController(t)
mockLedger := mock_ledger.NewMockLedger(mockCtl)
agencyData, err := ioutil.ReadFile("testdata/agency.cert")
require.Nil(t, err)
nodeData, err := ioutil.ReadFile("testdata/node.cert")
require.Nil(t, err)
caData, err := ioutil.ReadFile("testdata/ca.cert")
require.Nil(t, err)
cert, err := libp2pcert.ParseCert(caData)
require.Nil(t, err)
for i := 0; i < peerCnt; i++ {
ID := i + 1
repo := &repo.Repo{
Key: &repo.Key{},
NetworkConfig: &repo.NetworkConfig{
N: uint64(peerCnt),
ID: uint64(ID),
},
Certs: &libp2pcert.Certs{
NodeCertData: nodeData,
AgencyCertData: agencyData,
CACert: cert,
},
Config: &repo.Config{
Ping: repo.Ping{
Duration: 2 * time.Second,
},
},
}
if certVerify {
repo.Config.Cert.Verify = true
} else {
repo.Config.Cert.Verify = false
}
idx := strings.LastIndex(addrs[i], "/p2p/")
local := addrs[i][:idx]
repo.NetworkConfig.LocalAddr = local
repo.Key.Libp2pPrivKey = nodeKeys[i]
repo.Key.PrivKey = privKeys[i]
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
address, err := privKeys[i].PublicKey().Address()
require.Nil(t, err)
vpInfo := &pb.VpInfo{
Id: uint64(ID),
Account: address.String(),
}
nodes[uint64(ID)] = vpInfo
swarm, err := peermgr.New(repo, log.NewWithModule("p2p"), mockLedger)
require.Nil(t, err)
err = swarm.Start()
require.Nil(t, err)
swarms = append(swarms, swarm)
}
return swarms, nodes
func TestRun(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
node.checkInterval = 200 * time.Millisecond
err := node.Start()
ast.Nil(err)
// test confChangeC
node.confChangeC <- raftpb.ConfChange{ID: uint64(2)}
// test rebroadcastTicker
txs := make([]*pb.Transaction, 0)
txs = append(txs, constructTx(1))
node.mempool.ProcessTransactions(txs, false, true)
time.Sleep(250 * time.Millisecond)
}

View File

@ -0,0 +1,280 @@
package etcdraft
import (
"context"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"testing"
"time"
"github.com/coreos/etcd/raft"
"github.com/coreos/etcd/raft/raftpb"
"github.com/golang/mock/gomock"
crypto2 "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/meshplus/bitxhub-kit/crypto"
"github.com/meshplus/bitxhub-kit/crypto/asym"
"github.com/meshplus/bitxhub-kit/crypto/asym/ecdsa"
"github.com/meshplus/bitxhub-kit/log"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/meshplus/bitxhub/internal/ledger/mock_ledger"
"github.com/meshplus/bitxhub/internal/model/events"
"github.com/meshplus/bitxhub/internal/repo"
"github.com/meshplus/bitxhub/pkg/order"
raftproto "github.com/meshplus/bitxhub/pkg/order/etcdraft/proto"
"github.com/meshplus/bitxhub/pkg/order/mempool"
"github.com/meshplus/bitxhub/pkg/peermgr"
libp2pcert "github.com/meshplus/go-libp2p-cert"
"github.com/stretchr/testify/require"
)
const to = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
func constructTx(nonce uint64) *pb.Transaction {
privK, _ := asym.GenerateKeyPair(crypto.Secp256k1)
pubKey := privK.PublicKey()
addr, _ := pubKey.Address()
tx := &pb.Transaction{Nonce: nonce}
tx.Timestamp = time.Now().UnixNano()
tx.From = addr
sig, _ := privK.Sign(tx.SignHash().Bytes())
tx.Signature = sig
tx.TransactionHash = tx.Hash()
tx.Nonce = nonce
return tx
}
func mockRaftNode(t *testing.T) *Node {
logger := log.NewWithModule("consensus")
batchTimerMgr := NewTimer(500*time.Millisecond, logger)
txCache := mempool.NewTxCache(25*time.Millisecond, uint64(2), logger)
walDir := filepath.Join("./testdata/storage", "wal")
snapDir := filepath.Join("./testdata/storage", "snap")
dbDir := filepath.Join("./testdata/storage", "state")
raftStorage, dbStorage, _ := CreateStorage(logger, walDir, snapDir, dbDir, raft.NewMemoryStorage())
repoRoot := "./testdata/"
raftConfig, _ := generateRaftConfig(repoRoot)
peerCnt := 4
swarms, _ := newSwarms(t, peerCnt, false)
mempoolConf := &mempool.Config{
ID: uint64(1),
ChainHeight: uint64(1),
Logger: logger,
BatchSize: raftConfig.RAFT.MempoolConfig.BatchSize,
PoolSize: raftConfig.RAFT.MempoolConfig.PoolSize,
TxSliceSize: raftConfig.RAFT.MempoolConfig.TxSliceSize,
TxSliceTimeout: raftConfig.RAFT.MempoolConfig.TxSliceTimeout,
}
mempoolInst := mempool.NewMempool(mempoolConf)
node := &Node{
id: uint64(1),
lastExec: uint64(1),
repoRoot: repoRoot,
logger: logger,
confChangeC: make(chan raftpb.ConfChange),
commitC: make(chan *pb.CommitEvent, 1024),
errorC: make(chan<- error),
msgC: make(chan []byte),
stateC: make(chan *mempool.ChainState),
proposeC: make(chan *raftproto.RequestBatch),
txCache: txCache,
batchTimerMgr: batchTimerMgr,
storage: dbStorage,
raftStorage: raftStorage,
mempool: mempoolInst,
tickTimeout: 500 * time.Millisecond,
checkInterval: 3 * time.Minute,
ctx: context.Background(),
peerMgr: swarms[0],
getChainMetaFunc: getChainMetaFunc,
}
node.syncer = &mockSync{}
return node
}
type mockSync struct{}
// SyncCFTBlocks fetches the block list from other node, and just fetches but not verifies the block
func (sync *mockSync) SyncCFTBlocks(begin, end uint64, blockCh chan *pb.Block) error {
for i := begin; i <= end; i++ {
blockHeight := i
header := &pb.BlockHeader{Number: blockHeight}
blockHash := &types.Hash{
RawHash: [types.HashLength]byte{0},
}
blockCh <- &pb.Block{BlockHeader: header, BlockHash: blockHash}
}
blockCh <- nil
return nil
}
// SyncBFTBlocks fetches the block list from quorum nodes, and verifies all the block
func (sync *mockSync) SyncBFTBlocks(begin, end uint64, metaHash *types.Hash, blockCh chan *pb.Block) error {
return nil
}
func getChainMetaFunc() *pb.ChainMeta {
blockHash := &types.Hash{
RawHash: [types.HashLength]byte{1},
}
return &pb.ChainMeta{
Height: uint64(1),
BlockHash: blockHash,
}
}
func listen(t *testing.T, order order.Order, swarm *peermgr.Swarm) {
orderMsgCh := make(chan events.OrderMessageEvent)
sub := swarm.SubscribeOrderMessage(orderMsgCh)
defer sub.Unsubscribe()
for {
select {
case ev := <-orderMsgCh:
err := order.Step(ev.Data)
require.Nil(t, err)
}
}
}
func generateTx() *pb.Transaction {
privKey, _ := asym.GenerateKeyPair(crypto.Secp256k1)
from, _ := privKey.PublicKey().Address()
tx := &pb.Transaction{
From: from,
To: types.NewAddressByStr(to),
Timestamp: time.Now().UnixNano(),
Nonce: 1,
}
_ = tx.Sign(privKey)
tx.TransactionHash = tx.Hash()
return tx
}
func peers(id uint64, addrs []string, ids []string) []*repo.NetworkNodes {
m := make([]*repo.NetworkNodes, 0, len(addrs))
for i, addr := range addrs {
m = append(m, &repo.NetworkNodes{
ID: uint64(i + 1),
Account: "",
Pid: ids[i],
Hosts: []string{addr},
})
}
return m
}
func genKeysAndConfig(t *testing.T, peerCnt int) ([]crypto2.PrivKey, []crypto.PrivateKey, []string, []string) {
var nodeKeys []crypto2.PrivKey
var privKeys []crypto.PrivateKey
var peers []string
var ids []string
port := 5001
for i := 0; i < peerCnt; i++ {
key, err := asym.GenerateKeyPair(crypto.ECDSA_P256)
require.Nil(t, err)
libp2pKey, err := convertToLibp2pPrivKey(key)
require.Nil(t, err)
nodeKeys = append(nodeKeys, libp2pKey)
id, err := peer.IDFromPublicKey(libp2pKey.GetPublic())
require.Nil(t, err)
peer := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/p2p/", port)
peers = append(peers, peer)
ids = append(ids, id.String())
port++
privKey, err := asym.GenerateKeyPair(crypto.Secp256k1)
require.Nil(t, err)
privKeys = append(privKeys, privKey)
}
return nodeKeys, privKeys, peers, ids
}
func convertToLibp2pPrivKey(privateKey crypto.PrivateKey) (crypto2.PrivKey, error) {
ecdsaPrivKey, ok := privateKey.(*ecdsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("convert to libp2p private key: not ecdsa private key")
}
libp2pPrivKey, _, err := crypto2.ECDSAKeyPairFromKey(ecdsaPrivKey.K)
if err != nil {
return nil, err
}
return libp2pPrivKey, nil
}
func newSwarms(t *testing.T, peerCnt int, certVerify bool) ([]*peermgr.Swarm, map[uint64]*pb.VpInfo) {
var swarms []*peermgr.Swarm
nodes := make(map[uint64]*pb.VpInfo)
nodeKeys, privKeys, addrs, ids := genKeysAndConfig(t, peerCnt)
mockCtl := gomock.NewController(t)
mockLedger := mock_ledger.NewMockLedger(mockCtl)
agencyData, err := ioutil.ReadFile("testdata/agency.cert")
require.Nil(t, err)
nodeData, err := ioutil.ReadFile("testdata/node.cert")
require.Nil(t, err)
caData, err := ioutil.ReadFile("testdata/ca.cert")
require.Nil(t, err)
cert, err := libp2pcert.ParseCert(caData)
require.Nil(t, err)
for i := 0; i < peerCnt; i++ {
ID := i + 1
repo := &repo.Repo{
Key: &repo.Key{},
NetworkConfig: &repo.NetworkConfig{
N: uint64(peerCnt),
ID: uint64(ID),
},
Certs: &libp2pcert.Certs{
NodeCertData: nodeData,
AgencyCertData: agencyData,
CACert: cert,
},
Config: &repo.Config{
Ping: repo.Ping{
Duration: 2 * time.Second,
},
},
}
if certVerify {
repo.Config.Cert.Verify = true
} else {
repo.Config.Cert.Verify = false
}
idx := strings.LastIndex(addrs[i], "/p2p/")
local := addrs[i][:idx]
repo.NetworkConfig.LocalAddr = local
repo.Key.Libp2pPrivKey = nodeKeys[i]
repo.Key.PrivKey = privKeys[i]
repo.NetworkConfig.Nodes = peers(uint64(i), addrs, ids)
address, err := privKeys[i].PublicKey().Address()
require.Nil(t, err)
vpInfo := &pb.VpInfo{
Id: uint64(ID),
Account: address.String(),
}
nodes[uint64(ID)] = vpInfo
swarm, err := peermgr.New(repo, log.NewWithModule("p2p"), mockLedger)
require.Nil(t, err)
err = swarm.Start()
require.Nil(t, err)
swarms = append(swarms, swarm)
}
return swarms, nodes
}

View File

@ -2,7 +2,6 @@ package etcdraft
import (
"fmt"
"io"
"os"
"path/filepath"
"sort"
@ -83,8 +82,7 @@ func CreateStorage(
}
} else {
// snapshot found
lg.Debugf("Loaded snapshot at Term %d and Index %d, Nodes: %+v",
snapshot.Metadata.Term, snapshot.Metadata.Index, snapshot.Metadata.ConfState.Nodes)
lg.Debugf("Loaded snapshot at Term %d and Index %d, Nodes: %+v", snapshot.Metadata.Term, snapshot.Metadata.Index, snapshot.Metadata.ConfState.Nodes)
}
w, st, ents, err := createOrReadWAL(lg, walDir, snapshot)
@ -157,17 +155,8 @@ func ListSnapshots(logger raft.Logger, snapDir string) []uint64 {
s, err := snap.Read(fpath)
if err != nil {
logger.Errorf("Snapshot file %s is corrupted: %s", fpath, err)
broken := fpath + ".broken"
if err = os.Rename(fpath, broken); err != nil {
logger.Errorf("Failed to rename corrupted snapshot file %s to %s: %s", fpath, broken, err)
} else {
logger.Debugf("Renaming corrupted snapshot file %s to %s", fpath, broken)
}
continue
}
snapshots = append(snapshots, s.Metadata.Index)
}
@ -189,10 +178,6 @@ func createOrReadWAL(lg raft.Logger, walDir string, snapshot *raftpb.Snapshot) (
// TODO(jay_guo) add metadata to be persisted with wal once we need it.
// use case could be data dump and restore on a new node.
w, err := wal.Create(walDir, nil)
if err == os.ErrExist {
lg.Fatalf("programming error, we've just checked that WAL does not exist")
}
if err != nil {
return nil, st, nil, errors.Errorf("failed to initialize WAL: %s", err)
}
@ -212,46 +197,17 @@ func createOrReadWAL(lg raft.Logger, walDir string, snapshot *raftpb.Snapshot) (
lg.Debugf("Loading WAL at Term %d and Index %d", walsnap.Term, walsnap.Index)
var repaired bool
for {
if w, err = wal.Open(walDir, walsnap); err != nil {
return nil, st, nil, errors.Errorf("failed to open WAL: %s", err)
}
if _, st, ents, err = w.ReadAll(); err != nil {
lg.Warningf("Failed to read WAL: %s", err)
if errc := w.Close(); errc != nil {
return nil, st, nil, errors.Errorf("failed to close erroneous WAL: %s", errc)
}
// only repair UnexpectedEOF and only repair once
if repaired || err != io.ErrUnexpectedEOF {
return nil, st, nil, errors.Errorf("failed to read WAL and cannot repair: %s", err)
}
if !wal.Repair(walDir) {
return nil, st, nil, errors.Errorf("failed to repair WAL: %s", err)
}
repaired = true
// next loop should be able to open WAL and return
continue
}
// successfully opened WAL and read all entries, break
break
return nil, st, nil, errors.Errorf("failed to read WAL: %s", err)
}
return w, st, ents, nil
}
// Snapshot returns the latest snapshot stored in memory
func (rs *RaftStorage) Snapshot() raftpb.Snapshot {
sn, _ := rs.ram.Snapshot() // Snapshot always returns nil error
return sn
}
// Store persists etcd/raft data
func (rs *RaftStorage) Store(entries []raftpb.Entry, hardstate raftpb.HardState, snapshot raftpb.Snapshot) error {
if err := rs.wal.Save(hardstate, entries); err != nil {
@ -263,13 +219,8 @@ func (rs *RaftStorage) Store(entries []raftpb.Entry, hardstate raftpb.HardState,
return err
}
if err := rs.ram.ApplySnapshot(snapshot); err != nil {
if err == raft.ErrSnapOutOfDate {
rs.lg.Warningf("Attempted to apply out-of-date snapshot at Term %d and Index %d",
snapshot.Metadata.Term, snapshot.Metadata.Index)
} else {
rs.lg.Fatalf("Unexpected programming error: %s", err)
}
if err := rs.ram.ApplySnapshot(snapshot); err != nil && err != raft.ErrSnapOutOfDate {
return err
}
}
@ -325,12 +276,8 @@ func (rs *RaftStorage) TakeSnapshot(i uint64, cs raftpb.ConfState, data []byte)
if i > rs.SnapshotCatchUpEntries {
compacti := i - rs.SnapshotCatchUpEntries
rs.lg.Debugf("Purging in-memory raft entries prior to %d", compacti)
if err = rs.ram.Compact(compacti); err != nil {
if err == raft.ErrCompacted {
rs.lg.Warningf("Raft entries prior to %d are already purged", compacti)
} else {
rs.lg.Fatalf("Failed to purge raft entries: %s", err)
}
if err = rs.ram.Compact(compacti); err != nil && err != raft.ErrCompacted {
return err
}
}
@ -395,10 +342,6 @@ func (rs *RaftStorage) purgeSnap() {
var files []string
for _, f := range snapFiles {
if !strings.HasSuffix(f, ".snap") {
if strings.HasPrefix(f, ".broken") {
rs.lg.Warningf("Found broken snapshot file %s, it can be removed manually", f)
}
continue
}
@ -433,18 +376,6 @@ func (rs *RaftStorage) purge(files []string) {
}
}
// ApplySnapshot applies snapshot to local memory storage
func (rs *RaftStorage) ApplySnapshot(snap raftpb.Snapshot) {
if err := rs.ram.ApplySnapshot(snap); err != nil {
if err == raft.ErrSnapOutOfDate {
rs.lg.Warningf("Attempted to apply out-of-date snapshot at Term %d and Index %d",
snap.Metadata.Term, snap.Metadata.Index)
} else {
rs.lg.Fatalf("Unexpected programming error: %s", err)
}
}
}
// Close closes storage
func (rs *RaftStorage) Close() error {
if err := rs.wal.Close(); err != nil {

View File

@ -0,0 +1,111 @@
package etcdraft
import (
"os"
"testing"
"github.com/coreos/etcd/raft/raftpb"
"github.com/meshplus/bitxhub-kit/types"
"github.com/meshplus/bitxhub-model/pb"
"github.com/stretchr/testify/assert"
)
func TestRecoverFromSnapshot(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
err := node.Start()
ast.Nil(err)
snap := raftpb.Snapshot{Data: []byte("test"), Metadata: raftpb.SnapshotMetadata{Index: uint64(2), Term: uint64(1)}}
err = node.raftStorage.snap.SaveSnap(snap)
ast.Nil(err)
node.recoverFromSnapshot()
ast.NotEqual(uint64(2), node.appliedIndex, "wrong type data")
ast.NotEqual(uint64(2), node.snapshotIndex, "wrong type data")
go func() {
block := <-node.commitC
ast.Equal(uint64(2), block.Block.BlockHeader.Number)
}()
blockHash := &types.Hash{
RawHash: [types.HashLength]byte{2},
}
snapData := &pb.ChainMeta{Height: uint64(2), BlockHash: blockHash}
snapDataBytes, _ := snapData.Marshal()
snap.Data = snapDataBytes
err = node.raftStorage.snap.SaveSnap(snap)
ast.Nil(err)
node.recoverFromSnapshot()
ast.Equal(uint64(2), node.appliedIndex)
ast.Equal(uint64(2), node.snapshotIndex)
}
func TestTakeSnapshotAndGC(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
err := node.Start()
ast.Nil(err)
entries := []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(1)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(1), node.confState, []byte("test"))
ast.Nil(err)
ast.Equal(1, len(node.raftStorage.snapshotIndex))
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(2)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(2), node.confState, []byte("test2"))
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(3)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(3), node.confState, []byte("test3"))
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(4)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(4), node.confState, []byte("test4"))
ast.Equal(4, len(node.raftStorage.snapshotIndex))
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(5)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(5), node.confState, []byte("test5"))
ast.Equal(5, len(node.raftStorage.snapshotIndex))
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(6)}}
node.raftStorage.ram.Append(entries)
err = node.raftStorage.TakeSnapshot(uint64(6), node.confState, []byte("test6"))
ast.Equal(5, len(node.raftStorage.snapshotIndex), "gc Snap and wal 1")
err = node.raftStorage.Close()
ast.Nil(err)
}
func TestCreateOrReadWAL(t *testing.T) {
ast := assert.New(t)
defer os.RemoveAll("./testdata/storage")
node := mockRaftNode(t)
err := node.Start()
ast.Nil(err)
entries := []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(1)}}
snap := raftpb.Snapshot{Data: []byte("test"), Metadata: raftpb.SnapshotMetadata{Index: uint64(2), Term: uint64(1)}}
blockHash := &types.Hash{
RawHash: [types.HashLength]byte{2},
}
snapData := &pb.ChainMeta{Height: uint64(2), BlockHash: blockHash}
snapDataBytes, _ := snapData.Marshal()
snap.Data = snapDataBytes
hardstate := raftpb.HardState{Term: uint64(1), Commit: uint64(0)}
err = node.raftStorage.Store(entries, hardstate, snap)
ast.Nil(err)
_, _, _, err = createOrReadWAL(node.logger, node.raftStorage.walDir, &snap)
ast.NotNil(err, "requested entry index 1 is older than the existing snapshot 2")
entries = []raftpb.Entry{raftpb.Entry{Term: uint64(1), Index: uint64(4)}}
snap.Metadata.Index = uint64(3)
err = node.raftStorage.Store(entries, hardstate, snap)
ast.Nil(err)
_ = node.raftStorage.wal.Close()
_, st, ents, err1 := createOrReadWAL(node.logger, node.raftStorage.walDir, &snap)
ast.Nil(err1)
ast.Equal(uint64(1), st.Term)
ast.Equal(1, len(ents))
}

View File

@ -59,6 +59,8 @@ func TestGetPendingNonceByAccount(t *testing.T) {
ast.Equal(uint64(3), nonce)
nonce = mpi.GetPendingNonceByAccount(account2.String())
ast.Equal(uint64(3), nonce, "not 4")
ifFull := mpi.IsPoolFull()
ast.Equal(false, ifFull)
}
func TestCommitTransactions(t *testing.T) {