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