network_test.go 23 KB

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