package plugins import ( "testing" "time" "cwtch.im/cwtch/event" "cwtch.im/cwtch/protocol/connections" "git.openprivacy.ca/openprivacy/log" ) // TestContactRetryQueue simulates some basic connection queueing // NOTE: This whole test is a race condition, and does flag go's detector // We are invasively checking the internal state of the retry plugin and accessing pointers from another // thread. // We could build an entire thread safe monitoring functonality, but that would dramatically expand the scope of this test. func TestContactRetryQueue(t *testing.T) { log.SetLevel(log.LevelDebug) bus := event.NewEventManager() cr := NewConnectionRetry(bus, "").(*contactRetry) cr.ACNUp = true // fake an ACN connection... cr.protocolEngine = true // fake protocol engine cr.stallRetries = false // fake not being in offline mode... go cr.run() testOnion := "2wgvbza2mbuc72a4u6r6k4hc2blcvrmk4q26bfvlwbqxv2yq5k52fcqd" t.Logf("contact plugin up and running..sending peer connection...") // Assert that there is a peer connection identified as "test" bus.Publish(event.NewEvent(event.QueuePeerRequest, map[event.Field]string{event.RemotePeer: testOnion, event.LastSeen: "test"})) // Wait until the test actually exists, and is queued // This is the worst part of this test setup. Ideally we would sleep, or some other yielding, but // go test scheduling doesn't like that and even sleeping long periods won't cause the event thread to make // progress... setup := false for !setup { if _, exists := cr.connections.Load(testOnion); exists { if _, exists := cr.authorizedPeers.Load(testOnion); exists { t.Logf("authorized") setup = true } } } // We should very quickly become connecting... time.Sleep(time.Second) pinf, _ := cr.connections.Load(testOnion) if pinf.(*contact).state != 1 { t.Fatalf("test connection should be in connecting after update, actually: %v", pinf.(*contact).state) } // Asset that "test" is authenticated cr.handleEvent(testOnion, connections.AUTHENTICATED, peerConn) // Assert that "test has a valid state" pinf, _ = cr.connections.Load(testOnion) if pinf.(*contact).state != 3 { t.Fatalf("test connection should be in authenticated after update, actually: %v", pinf.(*contact).state) } // Publish an unrelated event to trigger the Plugin to go through a queuing cycle // If we didn't do this we would have to wait 30 seconds for a check-in bus.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{event.RemotePeer: "test2", event.ConnectionState: "Disconnected"})) bus.Publish(event.NewEvent(event.QueuePeerRequest, map[event.Field]string{event.RemotePeer: testOnion, event.LastSeen: time.Now().Format(time.RFC3339Nano)})) time.Sleep(time.Second) pinf, _ = cr.connections.Load(testOnion) if pinf.(*contact).state != 1 { t.Fatalf("test connection should be in connecting after update, actually: %v", pinf.(*contact).state) } cr.Shutdown() } // Takes around 4 min unless you adjust the consts for tickTimeSec and circuitTimeoutSecs /* func TestRetryEmission(t *testing.T) { log.SetLevel(log.LevelDebug) log.Infof("*** Starting TestRetryEmission! ***") bus := event.NewEventManager() testQueue := event.NewQueue() bus.Subscribe(event.PeerRequest, testQueue) cr := NewConnectionRetry(bus, "").(*contactRetry) cr.Start() time.Sleep(100 * time.Millisecond) bus.Publish(event.NewEventList(event.ACNStatus, event.Progress, "100")) bus.Publish(event.NewEventList(event.ProtocolEngineCreated)) pub, _, _ := ed25519.GenerateKey(rand.Reader) peerAddr := tor.GetTorV3Hostname(pub) bus.Publish(event.NewEventList(event.QueuePeerRequest, event.RemotePeer, peerAddr, event.LastSeen, time.Now().Format(time.RFC3339Nano))) log.Infof("Fetching 1st event") ev := testQueue.Next() if ev.EventType != event.PeerRequest { t.Errorf("1st event emitted was %v, expected %v", ev.EventType, event.PeerRequest) } log.Infof("1st event: %v", ev) bus.Publish(event.NewEventList(event.PeerStateChange, event.RemotePeer, peerAddr, event.ConnectionState, connections.ConnectionStateName[connections.DISCONNECTED])) log.Infof("fetching 2nd event") ev = testQueue.Next() log.Infof("2nd event: %v", ev) if ev.EventType != event.PeerRequest { t.Errorf("2nd event emitted was %v, expected %v", ev.EventType, event.PeerRequest) } bus.Publish(event.NewEventList(event.PeerStateChange, event.RemotePeer, peerAddr, event.ConnectionState, connections.ConnectionStateName[connections.CONNECTED])) time.Sleep(100 * time.Millisecond) bus.Publish(event.NewEventList(event.PeerStateChange, event.RemotePeer, peerAddr, event.ConnectionState, connections.ConnectionStateName[connections.DISCONNECTED])) log.Infof("fetching 3rd event") ev = testQueue.Next() log.Infof("3nd event: %v", ev) if ev.EventType != event.PeerRequest { t.Errorf("3nd event emitted was %v, expected %v", ev.EventType, event.PeerRequest) } cr.Shutdown() } */