network_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. // Copyright 2017 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 simulations
  17. import (
  18. "bytes"
  19. "context"
  20. "encoding/json"
  21. "fmt"
  22. "reflect"
  23. "strconv"
  24. "strings"
  25. "testing"
  26. "time"
  27. "github.com/ethereum/go-ethereum/log"
  28. "github.com/ethereum/go-ethereum/node"
  29. "github.com/ethereum/go-ethereum/p2p/enode"
  30. "github.com/ethereum/go-ethereum/p2p/simulations/adapters"
  31. )
  32. // Tests that a created snapshot with a minimal service only contains the expected connections
  33. // and that a network when loaded with this snapshot only contains those same connections
  34. func TestSnapshot(t *testing.T) {
  35. // PART I
  36. // create snapshot from ring network
  37. // this is a minimal service, whose protocol will take exactly one message OR close of connection before quitting
  38. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  39. "noopwoop": func(ctx *adapters.ServiceContext, stack *node.Node) (node.Lifecycle, error) {
  40. return NewNoopService(nil), nil
  41. },
  42. })
  43. // create network
  44. network := NewNetwork(adapter, &NetworkConfig{
  45. DefaultService: "noopwoop",
  46. })
  47. // \todo consider making a member of network, set to true threadsafe when shutdown
  48. runningOne := true
  49. defer func() {
  50. if runningOne {
  51. network.Shutdown()
  52. }
  53. }()
  54. // create and start nodes
  55. nodeCount := 20
  56. ids := make([]enode.ID, nodeCount)
  57. for i := 0; i < nodeCount; i++ {
  58. conf := adapters.RandomNodeConfig()
  59. node, err := network.NewNodeWithConfig(conf)
  60. if err != nil {
  61. t.Fatalf("error creating node: %s", err)
  62. }
  63. if err := network.Start(node.ID()); err != nil {
  64. t.Fatalf("error starting node: %s", err)
  65. }
  66. ids[i] = node.ID()
  67. }
  68. // subscribe to peer events
  69. evC := make(chan *Event)
  70. sub := network.Events().Subscribe(evC)
  71. defer sub.Unsubscribe()
  72. // connect nodes in a ring
  73. // spawn separate thread to avoid deadlock in the event listeners
  74. connectErr := make(chan error, 1)
  75. go func() {
  76. for i, id := range ids {
  77. peerID := ids[(i+1)%len(ids)]
  78. if err := network.Connect(id, peerID); err != nil {
  79. connectErr <- err
  80. return
  81. }
  82. }
  83. }()
  84. // collect connection events up to expected number
  85. ctx, cancel := context.WithTimeout(context.TODO(), time.Second)
  86. defer cancel()
  87. checkIds := make(map[enode.ID][]enode.ID)
  88. connEventCount := nodeCount
  89. OUTER:
  90. for {
  91. select {
  92. case <-ctx.Done():
  93. t.Fatal(ctx.Err())
  94. case err := <-connectErr:
  95. t.Fatal(err)
  96. case ev := <-evC:
  97. if ev.Type == EventTypeConn && !ev.Control {
  98. // fail on any disconnect
  99. if !ev.Conn.Up {
  100. t.Fatalf("unexpected disconnect: %v -> %v", ev.Conn.One, ev.Conn.Other)
  101. }
  102. checkIds[ev.Conn.One] = append(checkIds[ev.Conn.One], ev.Conn.Other)
  103. checkIds[ev.Conn.Other] = append(checkIds[ev.Conn.Other], ev.Conn.One)
  104. connEventCount--
  105. log.Debug("ev", "count", connEventCount)
  106. if connEventCount == 0 {
  107. break OUTER
  108. }
  109. }
  110. }
  111. }
  112. // create snapshot of current network
  113. snap, err := network.Snapshot()
  114. if err != nil {
  115. t.Fatal(err)
  116. }
  117. j, err := json.Marshal(snap)
  118. if err != nil {
  119. t.Fatal(err)
  120. }
  121. log.Debug("snapshot taken", "nodes", len(snap.Nodes), "conns", len(snap.Conns), "json", string(j))
  122. // verify that the snap element numbers check out
  123. if len(checkIds) != len(snap.Conns) || len(checkIds) != len(snap.Nodes) {
  124. t.Fatalf("snapshot wrong node,conn counts %d,%d != %d", len(snap.Nodes), len(snap.Conns), len(checkIds))
  125. }
  126. // shut down sim network
  127. runningOne = false
  128. sub.Unsubscribe()
  129. network.Shutdown()
  130. // check that we have all the expected connections in the snapshot
  131. for nodid, nodConns := range checkIds {
  132. for _, nodConn := range nodConns {
  133. var match bool
  134. for _, snapConn := range snap.Conns {
  135. if snapConn.One == nodid && snapConn.Other == nodConn {
  136. match = true
  137. break
  138. } else if snapConn.Other == nodid && snapConn.One == nodConn {
  139. match = true
  140. break
  141. }
  142. }
  143. if !match {
  144. t.Fatalf("snapshot missing conn %v -> %v", nodid, nodConn)
  145. }
  146. }
  147. }
  148. log.Info("snapshot checked")
  149. // PART II
  150. // load snapshot and verify that exactly same connections are formed
  151. adapter = adapters.NewSimAdapter(adapters.LifecycleConstructors{
  152. "noopwoop": func(ctx *adapters.ServiceContext, stack *node.Node) (node.Lifecycle, error) {
  153. return NewNoopService(nil), nil
  154. },
  155. })
  156. network = NewNetwork(adapter, &NetworkConfig{
  157. DefaultService: "noopwoop",
  158. })
  159. defer func() {
  160. network.Shutdown()
  161. }()
  162. // subscribe to peer events
  163. // every node up and conn up event will generate one additional control event
  164. // therefore multiply the count by two
  165. evC = make(chan *Event, (len(snap.Conns)*2)+(len(snap.Nodes)*2))
  166. sub = network.Events().Subscribe(evC)
  167. defer sub.Unsubscribe()
  168. // load the snapshot
  169. // spawn separate thread to avoid deadlock in the event listeners
  170. err = network.Load(snap)
  171. if err != nil {
  172. t.Fatal(err)
  173. }
  174. // collect connection events up to expected number
  175. ctx, cancel = context.WithTimeout(context.TODO(), time.Second*3)
  176. defer cancel()
  177. connEventCount = nodeCount
  178. OuterTwo:
  179. for {
  180. select {
  181. case <-ctx.Done():
  182. t.Fatal(ctx.Err())
  183. case ev := <-evC:
  184. if ev.Type == EventTypeConn && !ev.Control {
  185. // fail on any disconnect
  186. if !ev.Conn.Up {
  187. t.Fatalf("unexpected disconnect: %v -> %v", ev.Conn.One, ev.Conn.Other)
  188. }
  189. log.Debug("conn", "on", ev.Conn.One, "other", ev.Conn.Other)
  190. checkIds[ev.Conn.One] = append(checkIds[ev.Conn.One], ev.Conn.Other)
  191. checkIds[ev.Conn.Other] = append(checkIds[ev.Conn.Other], ev.Conn.One)
  192. connEventCount--
  193. log.Debug("ev", "count", connEventCount)
  194. if connEventCount == 0 {
  195. break OuterTwo
  196. }
  197. }
  198. }
  199. }
  200. // check that we have all expected connections in the network
  201. for _, snapConn := range snap.Conns {
  202. var match bool
  203. for nodid, nodConns := range checkIds {
  204. for _, nodConn := range nodConns {
  205. if snapConn.One == nodid && snapConn.Other == nodConn {
  206. match = true
  207. break
  208. } else if snapConn.Other == nodid && snapConn.One == nodConn {
  209. match = true
  210. break
  211. }
  212. }
  213. }
  214. if !match {
  215. t.Fatalf("network missing conn %v -> %v", snapConn.One, snapConn.Other)
  216. }
  217. }
  218. // verify that network didn't generate any other additional connection events after the ones we have collected within a reasonable period of time
  219. ctx, cancel = context.WithTimeout(context.TODO(), time.Second)
  220. defer cancel()
  221. select {
  222. case <-ctx.Done():
  223. case ev := <-evC:
  224. if ev.Type == EventTypeConn {
  225. t.Fatalf("Superfluous conn found %v -> %v", ev.Conn.One, ev.Conn.Other)
  226. }
  227. }
  228. // This test validates if all connections from the snapshot
  229. // are created in the network.
  230. t.Run("conns after load", func(t *testing.T) {
  231. // Create new network.
  232. n := NewNetwork(
  233. adapters.NewSimAdapter(adapters.LifecycleConstructors{
  234. "noopwoop": func(ctx *adapters.ServiceContext, stack *node.Node) (node.Lifecycle, error) {
  235. return NewNoopService(nil), nil
  236. },
  237. }),
  238. &NetworkConfig{
  239. DefaultService: "noopwoop",
  240. },
  241. )
  242. defer n.Shutdown()
  243. // Load the same snapshot.
  244. err := n.Load(snap)
  245. if err != nil {
  246. t.Fatal(err)
  247. }
  248. // Check every connection from the snapshot
  249. // if it is in the network, too.
  250. for _, c := range snap.Conns {
  251. if n.GetConn(c.One, c.Other) == nil {
  252. t.Errorf("missing connection: %s -> %s", c.One, c.Other)
  253. }
  254. }
  255. })
  256. }
  257. // TestNetworkSimulation creates a multi-node simulation network with each node
  258. // connected in a ring topology, checks that all nodes successfully handshake
  259. // with each other and that a snapshot fully represents the desired topology
  260. func TestNetworkSimulation(t *testing.T) {
  261. // create simulation network with 20 testService nodes
  262. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  263. "test": newTestService,
  264. })
  265. network := NewNetwork(adapter, &NetworkConfig{
  266. DefaultService: "test",
  267. })
  268. defer network.Shutdown()
  269. nodeCount := 20
  270. ids := make([]enode.ID, nodeCount)
  271. for i := 0; i < nodeCount; i++ {
  272. conf := adapters.RandomNodeConfig()
  273. node, err := network.NewNodeWithConfig(conf)
  274. if err != nil {
  275. t.Fatalf("error creating node: %s", err)
  276. }
  277. if err := network.Start(node.ID()); err != nil {
  278. t.Fatalf("error starting node: %s", err)
  279. }
  280. ids[i] = node.ID()
  281. }
  282. // perform a check which connects the nodes in a ring (so each node is
  283. // connected to exactly two peers) and then checks that all nodes
  284. // performed two handshakes by checking their peerCount
  285. action := func(_ context.Context) error {
  286. for i, id := range ids {
  287. peerID := ids[(i+1)%len(ids)]
  288. if err := network.Connect(id, peerID); err != nil {
  289. return err
  290. }
  291. }
  292. return nil
  293. }
  294. check := func(ctx context.Context, id enode.ID) (bool, error) {
  295. // check we haven't run out of time
  296. select {
  297. case <-ctx.Done():
  298. return false, ctx.Err()
  299. default:
  300. }
  301. // get the node
  302. node := network.GetNode(id)
  303. if node == nil {
  304. return false, fmt.Errorf("unknown node: %s", id)
  305. }
  306. // check it has exactly two peers
  307. client, err := node.Client()
  308. if err != nil {
  309. return false, err
  310. }
  311. var peerCount int64
  312. if err := client.CallContext(ctx, &peerCount, "test_peerCount"); err != nil {
  313. return false, err
  314. }
  315. switch {
  316. case peerCount < 2:
  317. return false, nil
  318. case peerCount == 2:
  319. return true, nil
  320. default:
  321. return false, fmt.Errorf("unexpected peerCount: %d", peerCount)
  322. }
  323. }
  324. timeout := 30 * time.Second
  325. ctx, cancel := context.WithTimeout(context.Background(), timeout)
  326. defer cancel()
  327. // trigger a check every 100ms
  328. trigger := make(chan enode.ID)
  329. go triggerChecks(ctx, ids, trigger, 100*time.Millisecond)
  330. result := NewSimulation(network).Run(ctx, &Step{
  331. Action: action,
  332. Trigger: trigger,
  333. Expect: &Expectation{
  334. Nodes: ids,
  335. Check: check,
  336. },
  337. })
  338. if result.Error != nil {
  339. t.Fatalf("simulation failed: %s", result.Error)
  340. }
  341. // take a network snapshot and check it contains the correct topology
  342. snap, err := network.Snapshot()
  343. if err != nil {
  344. t.Fatal(err)
  345. }
  346. if len(snap.Nodes) != nodeCount {
  347. t.Fatalf("expected snapshot to contain %d nodes, got %d", nodeCount, len(snap.Nodes))
  348. }
  349. if len(snap.Conns) != nodeCount {
  350. t.Fatalf("expected snapshot to contain %d connections, got %d", nodeCount, len(snap.Conns))
  351. }
  352. for i, id := range ids {
  353. conn := snap.Conns[i]
  354. if conn.One != id {
  355. t.Fatalf("expected conn[%d].One to be %s, got %s", i, id, conn.One)
  356. }
  357. peerID := ids[(i+1)%len(ids)]
  358. if conn.Other != peerID {
  359. t.Fatalf("expected conn[%d].Other to be %s, got %s", i, peerID, conn.Other)
  360. }
  361. }
  362. }
  363. func createTestNodes(count int, network *Network) (nodes []*Node, err error) {
  364. for i := 0; i < count; i++ {
  365. nodeConf := adapters.RandomNodeConfig()
  366. node, err := network.NewNodeWithConfig(nodeConf)
  367. if err != nil {
  368. return nil, err
  369. }
  370. if err := network.Start(node.ID()); err != nil {
  371. return nil, err
  372. }
  373. nodes = append(nodes, node)
  374. }
  375. return nodes, nil
  376. }
  377. func createTestNodesWithProperty(property string, count int, network *Network) (propertyNodes []*Node, err error) {
  378. for i := 0; i < count; i++ {
  379. nodeConf := adapters.RandomNodeConfig()
  380. nodeConf.Properties = append(nodeConf.Properties, property)
  381. node, err := network.NewNodeWithConfig(nodeConf)
  382. if err != nil {
  383. return nil, err
  384. }
  385. if err := network.Start(node.ID()); err != nil {
  386. return nil, err
  387. }
  388. propertyNodes = append(propertyNodes, node)
  389. }
  390. return propertyNodes, nil
  391. }
  392. // TestGetNodeIDs creates a set of nodes and attempts to retrieve their IDs,.
  393. // It then tests again whilst excluding a node ID from being returned.
  394. // If a node ID is not returned, or more node IDs than expected are returned, the test fails.
  395. func TestGetNodeIDs(t *testing.T) {
  396. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  397. "test": newTestService,
  398. })
  399. network := NewNetwork(adapter, &NetworkConfig{
  400. DefaultService: "test",
  401. })
  402. defer network.Shutdown()
  403. numNodes := 5
  404. nodes, err := createTestNodes(numNodes, network)
  405. if err != nil {
  406. t.Fatalf("Could not creat test nodes %v", err)
  407. }
  408. gotNodeIDs := network.GetNodeIDs()
  409. if len(gotNodeIDs) != numNodes {
  410. t.Fatalf("Expected %d nodes, got %d", numNodes, len(gotNodeIDs))
  411. }
  412. for _, node1 := range nodes {
  413. match := false
  414. for _, node2ID := range gotNodeIDs {
  415. if bytes.Equal(node1.ID().Bytes(), node2ID.Bytes()) {
  416. match = true
  417. break
  418. }
  419. }
  420. if !match {
  421. t.Fatalf("A created node was not returned by GetNodes(), ID: %s", node1.ID().String())
  422. }
  423. }
  424. excludeNodeID := nodes[3].ID()
  425. gotNodeIDsExcl := network.GetNodeIDs(excludeNodeID)
  426. if len(gotNodeIDsExcl) != numNodes-1 {
  427. t.Fatalf("Expected one less node ID to be returned")
  428. }
  429. for _, nodeID := range gotNodeIDsExcl {
  430. if bytes.Equal(excludeNodeID.Bytes(), nodeID.Bytes()) {
  431. t.Fatalf("GetNodeIDs returned the node ID we excluded, ID: %s", nodeID.String())
  432. }
  433. }
  434. }
  435. // TestGetNodes creates a set of nodes and attempts to retrieve them again.
  436. // It then tests again whilst excluding a node from being returned.
  437. // If a node is not returned, or more nodes than expected are returned, the test fails.
  438. func TestGetNodes(t *testing.T) {
  439. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  440. "test": newTestService,
  441. })
  442. network := NewNetwork(adapter, &NetworkConfig{
  443. DefaultService: "test",
  444. })
  445. defer network.Shutdown()
  446. numNodes := 5
  447. nodes, err := createTestNodes(numNodes, network)
  448. if err != nil {
  449. t.Fatalf("Could not creat test nodes %v", err)
  450. }
  451. gotNodes := network.GetNodes()
  452. if len(gotNodes) != numNodes {
  453. t.Fatalf("Expected %d nodes, got %d", numNodes, len(gotNodes))
  454. }
  455. for _, node1 := range nodes {
  456. match := false
  457. for _, node2 := range gotNodes {
  458. if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
  459. match = true
  460. break
  461. }
  462. }
  463. if !match {
  464. t.Fatalf("A created node was not returned by GetNodes(), ID: %s", node1.ID().String())
  465. }
  466. }
  467. excludeNodeID := nodes[3].ID()
  468. gotNodesExcl := network.GetNodes(excludeNodeID)
  469. if len(gotNodesExcl) != numNodes-1 {
  470. t.Fatalf("Expected one less node to be returned")
  471. }
  472. for _, node := range gotNodesExcl {
  473. if bytes.Equal(excludeNodeID.Bytes(), node.ID().Bytes()) {
  474. t.Fatalf("GetNodes returned the node we excluded, ID: %s", node.ID().String())
  475. }
  476. }
  477. }
  478. // TestGetNodesByID creates a set of nodes and attempts to retrieve a subset of them by ID
  479. // If a node is not returned, or more nodes than expected are returned, the test fails.
  480. func TestGetNodesByID(t *testing.T) {
  481. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  482. "test": newTestService,
  483. })
  484. network := NewNetwork(adapter, &NetworkConfig{
  485. DefaultService: "test",
  486. })
  487. defer network.Shutdown()
  488. numNodes := 5
  489. nodes, err := createTestNodes(numNodes, network)
  490. if err != nil {
  491. t.Fatalf("Could not create test nodes: %v", err)
  492. }
  493. numSubsetNodes := 2
  494. subsetNodes := nodes[0:numSubsetNodes]
  495. var subsetNodeIDs []enode.ID
  496. for _, node := range subsetNodes {
  497. subsetNodeIDs = append(subsetNodeIDs, node.ID())
  498. }
  499. gotNodesByID := network.GetNodesByID(subsetNodeIDs)
  500. if len(gotNodesByID) != numSubsetNodes {
  501. t.Fatalf("Expected %d nodes, got %d", numSubsetNodes, len(gotNodesByID))
  502. }
  503. for _, node1 := range subsetNodes {
  504. match := false
  505. for _, node2 := range gotNodesByID {
  506. if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
  507. match = true
  508. break
  509. }
  510. }
  511. if !match {
  512. t.Fatalf("A created node was not returned by GetNodesByID(), ID: %s", node1.ID().String())
  513. }
  514. }
  515. }
  516. // TestGetNodesByProperty creates a subset of nodes with a property assigned.
  517. // GetNodesByProperty is then checked for correctness by comparing the nodes returned to those initially created.
  518. // If a node with a property is not found, or more nodes than expected are returned, the test fails.
  519. func TestGetNodesByProperty(t *testing.T) {
  520. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  521. "test": newTestService,
  522. })
  523. network := NewNetwork(adapter, &NetworkConfig{
  524. DefaultService: "test",
  525. })
  526. defer network.Shutdown()
  527. numNodes := 3
  528. _, err := createTestNodes(numNodes, network)
  529. if err != nil {
  530. t.Fatalf("Failed to create nodes: %v", err)
  531. }
  532. numPropertyNodes := 3
  533. propertyTest := "test"
  534. propertyNodes, err := createTestNodesWithProperty(propertyTest, numPropertyNodes, network)
  535. if err != nil {
  536. t.Fatalf("Failed to create nodes with property: %v", err)
  537. }
  538. gotNodesByProperty := network.GetNodesByProperty(propertyTest)
  539. if len(gotNodesByProperty) != numPropertyNodes {
  540. t.Fatalf("Expected %d nodes with a property, got %d", numPropertyNodes, len(gotNodesByProperty))
  541. }
  542. for _, node1 := range propertyNodes {
  543. match := false
  544. for _, node2 := range gotNodesByProperty {
  545. if bytes.Equal(node1.ID().Bytes(), node2.ID().Bytes()) {
  546. match = true
  547. break
  548. }
  549. }
  550. if !match {
  551. t.Fatalf("A created node with property was not returned by GetNodesByProperty(), ID: %s", node1.ID().String())
  552. }
  553. }
  554. }
  555. // TestGetNodeIDsByProperty creates a subset of nodes with a property assigned.
  556. // GetNodeIDsByProperty is then checked for correctness by comparing the node IDs returned to those initially created.
  557. // If a node ID with a property is not found, or more nodes IDs than expected are returned, the test fails.
  558. func TestGetNodeIDsByProperty(t *testing.T) {
  559. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  560. "test": newTestService,
  561. })
  562. network := NewNetwork(adapter, &NetworkConfig{
  563. DefaultService: "test",
  564. })
  565. defer network.Shutdown()
  566. numNodes := 3
  567. _, err := createTestNodes(numNodes, network)
  568. if err != nil {
  569. t.Fatalf("Failed to create nodes: %v", err)
  570. }
  571. numPropertyNodes := 3
  572. propertyTest := "test"
  573. propertyNodes, err := createTestNodesWithProperty(propertyTest, numPropertyNodes, network)
  574. if err != nil {
  575. t.Fatalf("Failed to created nodes with property: %v", err)
  576. }
  577. gotNodeIDsByProperty := network.GetNodeIDsByProperty(propertyTest)
  578. if len(gotNodeIDsByProperty) != numPropertyNodes {
  579. t.Fatalf("Expected %d nodes with a property, got %d", numPropertyNodes, len(gotNodeIDsByProperty))
  580. }
  581. for _, node1 := range propertyNodes {
  582. match := false
  583. id1 := node1.ID()
  584. for _, id2 := range gotNodeIDsByProperty {
  585. if bytes.Equal(id1.Bytes(), id2.Bytes()) {
  586. match = true
  587. break
  588. }
  589. }
  590. if !match {
  591. t.Fatalf("Not all nodes IDs were returned by GetNodeIDsByProperty(), ID: %s", id1.String())
  592. }
  593. }
  594. }
  595. func triggerChecks(ctx context.Context, ids []enode.ID, trigger chan enode.ID, interval time.Duration) {
  596. tick := time.NewTicker(interval)
  597. defer tick.Stop()
  598. for {
  599. select {
  600. case <-tick.C:
  601. for _, id := range ids {
  602. select {
  603. case trigger <- id:
  604. case <-ctx.Done():
  605. return
  606. }
  607. }
  608. case <-ctx.Done():
  609. return
  610. }
  611. }
  612. }
  613. // \todo: refactor to implement shapshots
  614. // and connect configuration methods once these are moved from
  615. // swarm/network/simulations/connect.go
  616. func BenchmarkMinimalService(b *testing.B) {
  617. b.Run("ring/32", benchmarkMinimalServiceTmp)
  618. }
  619. func benchmarkMinimalServiceTmp(b *testing.B) {
  620. // stop timer to discard setup time pollution
  621. args := strings.Split(b.Name(), "/")
  622. nodeCount, err := strconv.ParseInt(args[2], 10, 16)
  623. if err != nil {
  624. b.Fatal(err)
  625. }
  626. for i := 0; i < b.N; i++ {
  627. // this is a minimal service, whose protocol will close a channel upon run of protocol
  628. // making it possible to bench the time it takes for the service to start and protocol actually to be run
  629. protoCMap := make(map[enode.ID]map[enode.ID]chan struct{})
  630. adapter := adapters.NewSimAdapter(adapters.LifecycleConstructors{
  631. "noopwoop": func(ctx *adapters.ServiceContext, stack *node.Node) (node.Lifecycle, error) {
  632. protoCMap[ctx.Config.ID] = make(map[enode.ID]chan struct{})
  633. svc := NewNoopService(protoCMap[ctx.Config.ID])
  634. return svc, nil
  635. },
  636. })
  637. // create network
  638. network := NewNetwork(adapter, &NetworkConfig{
  639. DefaultService: "noopwoop",
  640. })
  641. defer network.Shutdown()
  642. // create and start nodes
  643. ids := make([]enode.ID, nodeCount)
  644. for i := 0; i < int(nodeCount); i++ {
  645. conf := adapters.RandomNodeConfig()
  646. node, err := network.NewNodeWithConfig(conf)
  647. if err != nil {
  648. b.Fatalf("error creating node: %s", err)
  649. }
  650. if err := network.Start(node.ID()); err != nil {
  651. b.Fatalf("error starting node: %s", err)
  652. }
  653. ids[i] = node.ID()
  654. }
  655. // ready, set, go
  656. b.ResetTimer()
  657. // connect nodes in a ring
  658. for i, id := range ids {
  659. peerID := ids[(i+1)%len(ids)]
  660. if err := network.Connect(id, peerID); err != nil {
  661. b.Fatal(err)
  662. }
  663. }
  664. // wait for all protocols to signal to close down
  665. ctx, cancel := context.WithTimeout(context.TODO(), time.Second)
  666. defer cancel()
  667. for nodid, peers := range protoCMap {
  668. for peerid, peerC := range peers {
  669. log.Debug("getting ", "node", nodid, "peer", peerid)
  670. select {
  671. case <-ctx.Done():
  672. b.Fatal(ctx.Err())
  673. case <-peerC:
  674. }
  675. }
  676. }
  677. }
  678. }
  679. func TestNode_UnmarshalJSON(t *testing.T) {
  680. t.Run("up_field", func(t *testing.T) {
  681. runNodeUnmarshalJSON(t, casesNodeUnmarshalJSONUpField())
  682. })
  683. t.Run("config_field", func(t *testing.T) {
  684. runNodeUnmarshalJSON(t, casesNodeUnmarshalJSONConfigField())
  685. })
  686. }
  687. func runNodeUnmarshalJSON(t *testing.T, tests []nodeUnmarshalTestCase) {
  688. t.Helper()
  689. for _, tt := range tests {
  690. t.Run(tt.name, func(t *testing.T) {
  691. var got *Node
  692. if err := json.Unmarshal([]byte(tt.marshaled), &got); err != nil {
  693. expectErrorMessageToContain(t, err, tt.wantErr)
  694. got = nil
  695. }
  696. expectNodeEquality(t, got, tt.want)
  697. })
  698. }
  699. }
  700. type nodeUnmarshalTestCase struct {
  701. name string
  702. marshaled string
  703. want *Node
  704. wantErr string
  705. }
  706. func expectErrorMessageToContain(t *testing.T, got error, want string) {
  707. t.Helper()
  708. if got == nil && want == "" {
  709. return
  710. }
  711. if got == nil && want != "" {
  712. t.Errorf("error was expected, got: nil, want: %v", want)
  713. return
  714. }
  715. if !strings.Contains(got.Error(), want) {
  716. t.Errorf(
  717. "unexpected error message, got %v, want: %v",
  718. want,
  719. got,
  720. )
  721. }
  722. }
  723. func expectNodeEquality(t *testing.T, got, want *Node) {
  724. t.Helper()
  725. if !reflect.DeepEqual(got, want) {
  726. t.Errorf("Node.UnmarshalJSON() = %v, want %v", got, want)
  727. }
  728. }
  729. func casesNodeUnmarshalJSONUpField() []nodeUnmarshalTestCase {
  730. return []nodeUnmarshalTestCase{
  731. {
  732. name: "empty json",
  733. marshaled: "{}",
  734. want: newNode(nil, nil, false),
  735. },
  736. {
  737. name: "a stopped node",
  738. marshaled: "{\"up\": false}",
  739. want: newNode(nil, nil, false),
  740. },
  741. {
  742. name: "a running node",
  743. marshaled: "{\"up\": true}",
  744. want: newNode(nil, nil, true),
  745. },
  746. {
  747. name: "invalid JSON value on valid key",
  748. marshaled: "{\"up\": foo}",
  749. wantErr: "invalid character",
  750. },
  751. {
  752. name: "invalid JSON key and value",
  753. marshaled: "{foo: bar}",
  754. wantErr: "invalid character",
  755. },
  756. {
  757. name: "bool value expected but got something else (string)",
  758. marshaled: "{\"up\": \"true\"}",
  759. wantErr: "cannot unmarshal string into Go struct",
  760. },
  761. }
  762. }
  763. func casesNodeUnmarshalJSONConfigField() []nodeUnmarshalTestCase {
  764. // Don't do a big fuss around testing, as adapters.NodeConfig should
  765. // handle it's own serialization. Just do a sanity check.
  766. return []nodeUnmarshalTestCase{
  767. {
  768. name: "Config field is omitted",
  769. marshaled: "{}",
  770. want: newNode(nil, nil, false),
  771. },
  772. {
  773. name: "Config field is nil",
  774. marshaled: "{\"config\": null}",
  775. want: newNode(nil, nil, false),
  776. },
  777. {
  778. name: "a non default Config field",
  779. marshaled: "{\"config\":{\"name\":\"node_ecdd0\",\"port\":44665}}",
  780. want: newNode(nil, &adapters.NodeConfig{Name: "node_ecdd0", Port: 44665}, false),
  781. },
  782. }
  783. }