node_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package node
  17. import (
  18. "errors"
  19. "io/ioutil"
  20. "os"
  21. "reflect"
  22. "testing"
  23. "github.com/ethereum/go-ethereum/crypto"
  24. "github.com/ethereum/go-ethereum/p2p"
  25. )
  26. var (
  27. testNodeKey, _ = crypto.GenerateKey()
  28. testNodeConfig = &Config{
  29. PrivateKey: testNodeKey,
  30. Name: "test node",
  31. }
  32. )
  33. // Tests that an empty protocol stack can be started, restarted and stopped.
  34. func TestNodeLifeCycle(t *testing.T) {
  35. stack, err := New(testNodeConfig)
  36. if err != nil {
  37. t.Fatalf("failed to create protocol stack: %v", err)
  38. }
  39. // Ensure that a stopped node can be stopped again
  40. for i := 0; i < 3; i++ {
  41. if err := stack.Stop(); err != ErrNodeStopped {
  42. t.Fatalf("iter %d: stop failure mismatch: have %v, want %v", i, err, ErrNodeStopped)
  43. }
  44. }
  45. // Ensure that a node can be successfully started, but only once
  46. if err := stack.Start(); err != nil {
  47. t.Fatalf("failed to start node: %v", err)
  48. }
  49. if err := stack.Start(); err != ErrNodeRunning {
  50. t.Fatalf("start failure mismatch: have %v, want %v ", err, ErrNodeRunning)
  51. }
  52. // Ensure that a node can be restarted arbitrarily many times
  53. for i := 0; i < 3; i++ {
  54. if err := stack.Restart(); err != nil {
  55. t.Fatalf("iter %d: failed to restart node: %v", i, err)
  56. }
  57. }
  58. // Ensure that a node can be stopped, but only once
  59. if err := stack.Stop(); err != nil {
  60. t.Fatalf("failed to stop node: %v", err)
  61. }
  62. if err := stack.Stop(); err != ErrNodeStopped {
  63. t.Fatalf("stop failure mismatch: have %v, want %v ", err, ErrNodeStopped)
  64. }
  65. }
  66. // Tests that if the data dir is already in use, an appropriate error is returned.
  67. func TestNodeUsedDataDir(t *testing.T) {
  68. // Create a temporary folder to use as the data directory
  69. dir, err := ioutil.TempDir("", "")
  70. if err != nil {
  71. t.Fatalf("failed to create temporary data directory: %v", err)
  72. }
  73. defer os.RemoveAll(dir)
  74. // Create a new node based on the data directory
  75. original, err := New(&Config{DataDir: dir})
  76. if err != nil {
  77. t.Fatalf("failed to create original protocol stack: %v", err)
  78. }
  79. if err := original.Start(); err != nil {
  80. t.Fatalf("failed to start original protocol stack: %v", err)
  81. }
  82. defer original.Stop()
  83. // Create a second node based on the same data directory and ensure failure
  84. duplicate, err := New(&Config{DataDir: dir})
  85. if err != nil {
  86. t.Fatalf("failed to create duplicate protocol stack: %v", err)
  87. }
  88. if err := duplicate.Start(); err != ErrDatadirUsed {
  89. t.Fatalf("duplicate datadir failure mismatch: have %v, want %v", err, ErrDatadirUsed)
  90. }
  91. }
  92. // Tests whether services can be registered and duplicates caught.
  93. func TestServiceRegistry(t *testing.T) {
  94. stack, err := New(testNodeConfig)
  95. if err != nil {
  96. t.Fatalf("failed to create protocol stack: %v", err)
  97. }
  98. // Register a batch of unique services and ensure they start successfully
  99. services := []ServiceConstructor{NewNoopServiceA, NewNoopServiceB, NewNoopServiceC}
  100. for i, constructor := range services {
  101. if err := stack.Register(constructor); err != nil {
  102. t.Fatalf("service #%d: registration failed: %v", i, err)
  103. }
  104. }
  105. if err := stack.Start(); err != nil {
  106. t.Fatalf("failed to start original service stack: %v", err)
  107. }
  108. if err := stack.Stop(); err != nil {
  109. t.Fatalf("failed to stop original service stack: %v", err)
  110. }
  111. // Duplicate one of the services and retry starting the node
  112. if err := stack.Register(NewNoopServiceB); err != nil {
  113. t.Fatalf("duplicate registration failed: %v", err)
  114. }
  115. if err := stack.Start(); err == nil {
  116. t.Fatalf("duplicate service started")
  117. } else {
  118. if _, ok := err.(*DuplicateServiceError); !ok {
  119. t.Fatalf("duplicate error mismatch: have %v, want %v", err, DuplicateServiceError{})
  120. }
  121. }
  122. }
  123. // Tests that registered services get started and stopped correctly.
  124. func TestServiceLifeCycle(t *testing.T) {
  125. stack, err := New(testNodeConfig)
  126. if err != nil {
  127. t.Fatalf("failed to create protocol stack: %v", err)
  128. }
  129. // Register a batch of life-cycle instrumented services
  130. services := map[string]InstrumentingWrapper{
  131. "A": InstrumentedServiceMakerA,
  132. "B": InstrumentedServiceMakerB,
  133. "C": InstrumentedServiceMakerC,
  134. }
  135. started := make(map[string]bool)
  136. stopped := make(map[string]bool)
  137. for id, maker := range services {
  138. id := id // Closure for the constructor
  139. constructor := func(*ServiceContext) (Service, error) {
  140. return &InstrumentedService{
  141. startHook: func(*p2p.Server) { started[id] = true },
  142. stopHook: func() { stopped[id] = true },
  143. }, nil
  144. }
  145. if err := stack.Register(maker(constructor)); err != nil {
  146. t.Fatalf("service %s: registration failed: %v", id, err)
  147. }
  148. }
  149. // Start the node and check that all services are running
  150. if err := stack.Start(); err != nil {
  151. t.Fatalf("failed to start protocol stack: %v", err)
  152. }
  153. for id, _ := range services {
  154. if !started[id] {
  155. t.Fatalf("service %s: freshly started service not running", id)
  156. }
  157. if stopped[id] {
  158. t.Fatalf("service %s: freshly started service already stopped", id)
  159. }
  160. }
  161. // Stop the node and check that all services have been stopped
  162. if err := stack.Stop(); err != nil {
  163. t.Fatalf("failed to stop protocol stack: %v", err)
  164. }
  165. for id, _ := range services {
  166. if !stopped[id] {
  167. t.Fatalf("service %s: freshly terminated service still running", id)
  168. }
  169. }
  170. }
  171. // Tests that services are restarted cleanly as new instances.
  172. func TestServiceRestarts(t *testing.T) {
  173. stack, err := New(testNodeConfig)
  174. if err != nil {
  175. t.Fatalf("failed to create protocol stack: %v", err)
  176. }
  177. // Define a service that does not support restarts
  178. var (
  179. running bool
  180. started int
  181. )
  182. constructor := func(*ServiceContext) (Service, error) {
  183. running = false
  184. return &InstrumentedService{
  185. startHook: func(*p2p.Server) {
  186. if running {
  187. panic("already running")
  188. }
  189. running = true
  190. started++
  191. },
  192. }, nil
  193. }
  194. // Register the service and start the protocol stack
  195. if err := stack.Register(constructor); err != nil {
  196. t.Fatalf("failed to register the service: %v", err)
  197. }
  198. if err := stack.Start(); err != nil {
  199. t.Fatalf("failed to start protocol stack: %v", err)
  200. }
  201. defer stack.Stop()
  202. if running != true || started != 1 {
  203. t.Fatalf("running/started mismatch: have %v/%d, want true/1", running, started)
  204. }
  205. // Restart the stack a few times and check successful service restarts
  206. for i := 0; i < 3; i++ {
  207. if err := stack.Restart(); err != nil {
  208. t.Fatalf("iter %d: failed to restart stack: %v", i, err)
  209. }
  210. }
  211. if running != true || started != 4 {
  212. t.Fatalf("running/started mismatch: have %v/%d, want true/4", running, started)
  213. }
  214. }
  215. // Tests that if a service fails to initialize itself, none of the other services
  216. // will be allowed to even start.
  217. func TestServiceConstructionAbortion(t *testing.T) {
  218. stack, err := New(testNodeConfig)
  219. if err != nil {
  220. t.Fatalf("failed to create protocol stack: %v", err)
  221. }
  222. // Define a batch of good services
  223. services := map[string]InstrumentingWrapper{
  224. "A": InstrumentedServiceMakerA,
  225. "B": InstrumentedServiceMakerB,
  226. "C": InstrumentedServiceMakerC,
  227. }
  228. started := make(map[string]bool)
  229. for id, maker := range services {
  230. id := id // Closure for the constructor
  231. constructor := func(*ServiceContext) (Service, error) {
  232. return &InstrumentedService{
  233. startHook: func(*p2p.Server) { started[id] = true },
  234. }, nil
  235. }
  236. if err := stack.Register(maker(constructor)); err != nil {
  237. t.Fatalf("service %s: registration failed: %v", id, err)
  238. }
  239. }
  240. // Register a service that fails to construct itself
  241. failure := errors.New("fail")
  242. failer := func(*ServiceContext) (Service, error) {
  243. return nil, failure
  244. }
  245. if err := stack.Register(failer); err != nil {
  246. t.Fatalf("failer registration failed: %v", err)
  247. }
  248. // Start the protocol stack and ensure none of the services get started
  249. for i := 0; i < 100; i++ {
  250. if err := stack.Start(); err != failure {
  251. t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure)
  252. }
  253. for id, _ := range services {
  254. if started[id] {
  255. t.Fatalf("service %s: started should not have", id)
  256. }
  257. delete(started, id)
  258. }
  259. }
  260. }
  261. // Tests that if a service fails to start, all others started before it will be
  262. // shut down.
  263. func TestServiceStartupAbortion(t *testing.T) {
  264. stack, err := New(testNodeConfig)
  265. if err != nil {
  266. t.Fatalf("failed to create protocol stack: %v", err)
  267. }
  268. // Register a batch of good services
  269. services := map[string]InstrumentingWrapper{
  270. "A": InstrumentedServiceMakerA,
  271. "B": InstrumentedServiceMakerB,
  272. "C": InstrumentedServiceMakerC,
  273. }
  274. started := make(map[string]bool)
  275. stopped := make(map[string]bool)
  276. for id, maker := range services {
  277. id := id // Closure for the constructor
  278. constructor := func(*ServiceContext) (Service, error) {
  279. return &InstrumentedService{
  280. startHook: func(*p2p.Server) { started[id] = true },
  281. stopHook: func() { stopped[id] = true },
  282. }, nil
  283. }
  284. if err := stack.Register(maker(constructor)); err != nil {
  285. t.Fatalf("service %s: registration failed: %v", id, err)
  286. }
  287. }
  288. // Register a service that fails to start
  289. failure := errors.New("fail")
  290. failer := func(*ServiceContext) (Service, error) {
  291. return &InstrumentedService{
  292. start: failure,
  293. }, nil
  294. }
  295. if err := stack.Register(failer); err != nil {
  296. t.Fatalf("failer registration failed: %v", err)
  297. }
  298. // Start the protocol stack and ensure all started services stop
  299. for i := 0; i < 100; i++ {
  300. if err := stack.Start(); err != failure {
  301. t.Fatalf("iter %d: stack startup failure mismatch: have %v, want %v", i, err, failure)
  302. }
  303. for id, _ := range services {
  304. if started[id] && !stopped[id] {
  305. t.Fatalf("service %s: started but not stopped", id)
  306. }
  307. delete(started, id)
  308. delete(stopped, id)
  309. }
  310. }
  311. }
  312. // Tests that even if a registered service fails to shut down cleanly, it does
  313. // not influece the rest of the shutdown invocations.
  314. func TestServiceTerminationGuarantee(t *testing.T) {
  315. stack, err := New(testNodeConfig)
  316. if err != nil {
  317. t.Fatalf("failed to create protocol stack: %v", err)
  318. }
  319. // Register a batch of good services
  320. services := map[string]InstrumentingWrapper{
  321. "A": InstrumentedServiceMakerA,
  322. "B": InstrumentedServiceMakerB,
  323. "C": InstrumentedServiceMakerC,
  324. }
  325. started := make(map[string]bool)
  326. stopped := make(map[string]bool)
  327. for id, maker := range services {
  328. id := id // Closure for the constructor
  329. constructor := func(*ServiceContext) (Service, error) {
  330. return &InstrumentedService{
  331. startHook: func(*p2p.Server) { started[id] = true },
  332. stopHook: func() { stopped[id] = true },
  333. }, nil
  334. }
  335. if err := stack.Register(maker(constructor)); err != nil {
  336. t.Fatalf("service %s: registration failed: %v", id, err)
  337. }
  338. }
  339. // Register a service that fails to shot down cleanly
  340. failure := errors.New("fail")
  341. failer := func(*ServiceContext) (Service, error) {
  342. return &InstrumentedService{
  343. stop: failure,
  344. }, nil
  345. }
  346. if err := stack.Register(failer); err != nil {
  347. t.Fatalf("failer registration failed: %v", err)
  348. }
  349. // Start the protocol stack, and ensure that a failing shut down terminates all
  350. for i := 0; i < 100; i++ {
  351. // Start the stack and make sure all is online
  352. if err := stack.Start(); err != nil {
  353. t.Fatalf("iter %d: failed to start protocol stack: %v", i, err)
  354. }
  355. for id, _ := range services {
  356. if !started[id] {
  357. t.Fatalf("iter %d, service %s: service not running", i, id)
  358. }
  359. if stopped[id] {
  360. t.Fatalf("iter %d, service %s: service already stopped", i, id)
  361. }
  362. }
  363. // Stop the stack, verify failure and check all terminations
  364. err := stack.Stop()
  365. if err, ok := err.(*StopError); !ok {
  366. t.Fatalf("iter %d: termination failure mismatch: have %v, want StopError", i, err)
  367. } else {
  368. failer := reflect.TypeOf(&InstrumentedService{})
  369. if err.Services[failer] != failure {
  370. t.Fatalf("iter %d: failer termination failure mismatch: have %v, want %v", i, err.Services[failer], failure)
  371. }
  372. if len(err.Services) != 1 {
  373. t.Fatalf("iter %d: failure count mismatch: have %d, want %d", i, len(err.Services), 1)
  374. }
  375. }
  376. for id, _ := range services {
  377. if !stopped[id] {
  378. t.Fatalf("iter %d, service %s: service not terminated", i, id)
  379. }
  380. delete(started, id)
  381. delete(stopped, id)
  382. }
  383. }
  384. }
  385. // TestServiceRetrieval tests that individual services can be retrieved.
  386. func TestServiceRetrieval(t *testing.T) {
  387. // Create a simple stack and register two service types
  388. stack, err := New(testNodeConfig)
  389. if err != nil {
  390. t.Fatalf("failed to create protocol stack: %v", err)
  391. }
  392. if err := stack.Register(NewNoopService); err != nil {
  393. t.Fatalf("noop service registration failed: %v", err)
  394. }
  395. if err := stack.Register(NewInstrumentedService); err != nil {
  396. t.Fatalf("instrumented service registration failed: %v", err)
  397. }
  398. // Make sure none of the services can be retrieved until started
  399. var noopServ *NoopService
  400. if err := stack.Service(&noopServ); err != ErrNodeStopped {
  401. t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, ErrNodeStopped)
  402. }
  403. var instServ *InstrumentedService
  404. if err := stack.Service(&instServ); err != ErrNodeStopped {
  405. t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, ErrNodeStopped)
  406. }
  407. // Start the stack and ensure everything is retrievable now
  408. if err := stack.Start(); err != nil {
  409. t.Fatalf("failed to start stack: %v", err)
  410. }
  411. defer stack.Stop()
  412. if err := stack.Service(&noopServ); err != nil {
  413. t.Fatalf("noop service retrieval mismatch: have %v, want %v", err, nil)
  414. }
  415. if err := stack.Service(&instServ); err != nil {
  416. t.Fatalf("instrumented service retrieval mismatch: have %v, want %v", err, nil)
  417. }
  418. }
  419. // Tests that all protocols defined by individual services get launched.
  420. func TestProtocolGather(t *testing.T) {
  421. stack, err := New(testNodeConfig)
  422. if err != nil {
  423. t.Fatalf("failed to create protocol stack: %v", err)
  424. }
  425. // Register a batch of services with some configured number of protocols
  426. services := map[string]struct {
  427. Count int
  428. Maker InstrumentingWrapper
  429. }{
  430. "Zero Protocols": {0, InstrumentedServiceMakerA},
  431. "Single Protocol": {1, InstrumentedServiceMakerB},
  432. "Many Protocols": {25, InstrumentedServiceMakerC},
  433. }
  434. for id, config := range services {
  435. protocols := make([]p2p.Protocol, config.Count)
  436. for i := 0; i < len(protocols); i++ {
  437. protocols[i].Name = id
  438. protocols[i].Version = uint(i)
  439. }
  440. constructor := func(*ServiceContext) (Service, error) {
  441. return &InstrumentedService{
  442. protocols: protocols,
  443. }, nil
  444. }
  445. if err := stack.Register(config.Maker(constructor)); err != nil {
  446. t.Fatalf("service %s: registration failed: %v", id, err)
  447. }
  448. }
  449. // Start the services and ensure all protocols start successfully
  450. if err := stack.Start(); err != nil {
  451. t.Fatalf("failed to start protocol stack: %v", err)
  452. }
  453. defer stack.Stop()
  454. protocols := stack.Server().Protocols
  455. if len(protocols) != 26 {
  456. t.Fatalf("mismatching number of protocols launched: have %d, want %d", len(protocols), 26)
  457. }
  458. for id, config := range services {
  459. for ver := 0; ver < config.Count; ver++ {
  460. launched := false
  461. for i := 0; i < len(protocols); i++ {
  462. if protocols[i].Name == id && protocols[i].Version == uint(ver) {
  463. launched = true
  464. break
  465. }
  466. }
  467. if !launched {
  468. t.Errorf("configured protocol not launched: %s v%d", id, ver)
  469. }
  470. }
  471. }
  472. }