github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/whisper/whisper_test.go (about) 1 // Copyright 2014 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 17 // +build !deterministic 18 19 package whisper 20 21 import ( 22 "testing" 23 "time" 24 25 "github.com/ethereumproject/go-ethereum/p2p" 26 "github.com/ethereumproject/go-ethereum/p2p/discover" 27 ) 28 29 func startTestCluster(n int) []*Whisper { 30 // Create the batch of simulated peers 31 nodes := make([]*p2p.Peer, n) 32 for i := 0; i < n; i++ { 33 nodes[i] = p2p.NewPeer(discover.NodeID{}, "", nil) 34 } 35 whispers := make([]*Whisper, n) 36 for i := 0; i < n; i++ { 37 whispers[i] = New() 38 whispers[i].Start(nil) 39 } 40 // Wire all the peers to the root one 41 for i := 1; i < n; i++ { 42 src, dst := p2p.MsgPipe() 43 44 go whispers[0].handlePeer(nodes[i], src) 45 go whispers[i].handlePeer(nodes[0], dst) 46 } 47 return whispers 48 } 49 50 func TestSelfMessage(t *testing.T) { 51 // Start the single node cluster 52 client := startTestCluster(1)[0] 53 54 // Start watching for self messages, signal any arrivals 55 self := client.NewIdentity() 56 done := make(chan struct{}) 57 58 client.Watch(Filter{ 59 To: &self.PublicKey, 60 Fn: func(msg *Message) { 61 close(done) 62 }, 63 }) 64 // Send a dummy message to oneself 65 msg := NewMessage([]byte("self whisper")) 66 envelope, err := msg.Wrap(DefaultPoW, Options{ 67 From: self, 68 To: &self.PublicKey, 69 TTL: DefaultTTL, 70 }) 71 if err != nil { 72 t.Fatalf("failed to wrap message: %v", err) 73 } 74 // Dump the message into the system and wait for it to pop back out 75 if err := client.Send(envelope); err != nil { 76 t.Fatalf("failed to send self-message: %v", err) 77 } 78 select { 79 case <-done: 80 case <-time.After(time.Second): 81 t.Fatalf("self-message receive timeout") 82 } 83 } 84 85 func TestDirectMessage(t *testing.T) { 86 // Start the sender-recipient cluster 87 cluster := startTestCluster(2) 88 89 sender := cluster[0] 90 senderId := sender.NewIdentity() 91 92 recipient := cluster[1] 93 recipientId := recipient.NewIdentity() 94 95 // Watch for arriving messages on the recipient 96 done := make(chan struct{}) 97 recipient.Watch(Filter{ 98 To: &recipientId.PublicKey, 99 Fn: func(msg *Message) { 100 close(done) 101 }, 102 }) 103 // Send a dummy message from the sender 104 msg := NewMessage([]byte("direct whisper")) 105 envelope, err := msg.Wrap(DefaultPoW, Options{ 106 From: senderId, 107 To: &recipientId.PublicKey, 108 TTL: DefaultTTL, 109 }) 110 if err != nil { 111 t.Fatalf("failed to wrap message: %v", err) 112 } 113 if err := sender.Send(envelope); err != nil { 114 t.Fatalf("failed to send direct message: %v", err) 115 } 116 // Wait for an arrival or a timeout 117 select { 118 case <-done: 119 case <-time.After(time.Second): 120 t.Fatalf("direct message receive timeout") 121 } 122 } 123 124 func TestAnonymousBroadcast(t *testing.T) { 125 testBroadcast(true, t) 126 } 127 128 func TestIdentifiedBroadcast(t *testing.T) { 129 testBroadcast(false, t) 130 } 131 132 func testBroadcast(anonymous bool, t *testing.T) { 133 // Start the single sender multi recipient cluster 134 cluster := startTestCluster(3) 135 136 sender := cluster[1] 137 targets := cluster[1:] 138 for _, target := range targets { 139 if !anonymous { 140 target.NewIdentity() 141 } 142 } 143 // Watch for arriving messages on the recipients 144 dones := make([]chan struct{}, len(targets)) 145 for i := 0; i < len(targets); i++ { 146 done := make(chan struct{}) // need for the closure 147 dones[i] = done 148 149 targets[i].Watch(Filter{ 150 Topics: newFilterTopicsFromStringsFlat("broadcast topic"), 151 Fn: func(msg *Message) { 152 close(done) 153 }, 154 }) 155 } 156 // Send a dummy message from the sender 157 msg := NewMessage([]byte("broadcast whisper")) 158 envelope, err := msg.Wrap(DefaultPoW, Options{ 159 Topics: newTopicsFromStrings("broadcast topic"), 160 TTL: DefaultTTL, 161 }) 162 if err != nil { 163 t.Fatalf("failed to wrap message: %v", err) 164 } 165 if err := sender.Send(envelope); err != nil { 166 t.Fatalf("failed to send broadcast message: %v", err) 167 } 168 // Wait for an arrival on each recipient, or timeouts 169 timeout := time.After(time.Second) 170 for _, done := range dones { 171 select { 172 case <-done: 173 case <-timeout: 174 t.Fatalf("broadcast message receive timeout") 175 } 176 } 177 } 178 179 func TestMessageExpiration(t *testing.T) { 180 // Start the single node cluster and inject a dummy message 181 node := startTestCluster(1)[0] 182 183 message := NewMessage([]byte("expiring message")) 184 envelope, err := message.Wrap(DefaultPoW, Options{TTL: time.Second}) 185 if err != nil { 186 t.Fatalf("failed to wrap message: %v", err) 187 } 188 if err := node.Send(envelope); err != nil { 189 t.Fatalf("failed to inject message: %v", err) 190 } 191 // Check that the message is inside the cache 192 node.poolMu.RLock() 193 _, found := node.messages[envelope.Hash()] 194 node.poolMu.RUnlock() 195 196 if !found { 197 t.Fatalf("message not found in cache") 198 } 199 // Wait for expiration and check cache again 200 time.Sleep(time.Second) // wait for expiration 201 time.Sleep(2 * expirationCycle) // wait for cleanup cycle 202 203 node.poolMu.RLock() 204 _, found = node.messages[envelope.Hash()] 205 node.poolMu.RUnlock() 206 if found { 207 t.Fatalf("message not expired from cache") 208 } 209 210 // Check that adding an expired envelope doesn't do anything. 211 node.add(envelope) 212 node.poolMu.RLock() 213 _, found = node.messages[envelope.Hash()] 214 node.poolMu.RUnlock() 215 if found { 216 t.Fatalf("message was added to cache") 217 } 218 }