Official cwtch.im peer and server implementations. https://cwtch.im
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cwtch_peer_server_integration_test.go 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. package testing
  2. import (
  3. app2 "cwtch.im/cwtch/app"
  4. "cwtch.im/cwtch/event"
  5. "cwtch.im/cwtch/model"
  6. "cwtch.im/cwtch/peer"
  7. "cwtch.im/cwtch/protocol/connections"
  8. cwtchserver "cwtch.im/cwtch/server"
  9. "fmt"
  10. "git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
  11. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  12. "golang.org/x/net/proxy"
  13. "os"
  14. "runtime"
  15. "runtime/pprof"
  16. "testing"
  17. "time"
  18. )
  19. const (
  20. serverKeyfile = "./../server/app/private_key"
  21. localKeyfile = "./private_key"
  22. )
  23. var (
  24. aliceLines = []string{"Hello, I'm Alice", "bye"}
  25. bobLines = []string{"Hi, my name is Bob.", "toodles", "welcome"}
  26. carolLines = []string{"Howdy, thanks!"}
  27. )
  28. func printAndCountVerifedTimeline(t *testing.T, timeline []model.Message) int {
  29. numVerified := 0
  30. for _, message := range timeline {
  31. fmt.Printf("%v %v> %s\n", message.Timestamp, message.PeerID, message.Message)
  32. numVerified++
  33. }
  34. return numVerified
  35. }
  36. func serverCheck(t *testing.T, serverAddr string) bool {
  37. torDialer, err := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct)
  38. if err != nil {
  39. t.Logf("Could not get SOCKS5 proxy: %v", err)
  40. return false
  41. }
  42. // Doesn't seem to be a way to turn the default timeout of 2 minutes down
  43. conn, err := torDialer.Dial("tcp", serverAddr+".onion:9878")
  44. if err != nil {
  45. t.Logf("Could not dial %v: %v", serverAddr, err)
  46. return false
  47. }
  48. conn.Close()
  49. return true
  50. }
  51. func waitForPeerGroupConnection(t *testing.T, peer peer.CwtchPeer, groupID string) {
  52. for {
  53. _, ok := peer.GetProfile().Groups[groupID]
  54. if ok {
  55. state := peer.GetGroupState(groupID)
  56. //log.Infof("Waiting for Peer %v to join group %v - state: %v\n", peer.GetProfile().Name, groupID, state)
  57. if state == connections.FAILED {
  58. t.Fatalf("%v could not connect to %v", peer.GetProfile().Onion, groupID)
  59. }
  60. if state != connections.AUTHENTICATED {
  61. fmt.Printf("peer %v waiting connect to group %v, currently: %v\n", peer.GetProfile().Onion, groupID, connections.ConnectionStateName[state])
  62. time.Sleep(time.Second * 5)
  63. continue
  64. } else {
  65. break
  66. }
  67. } // It might take a second for the server to show up as it is now going through the event bus
  68. time.Sleep(time.Second)
  69. }
  70. return
  71. }
  72. func waitForPeerPeerConnection(t *testing.T, peera peer.CwtchPeer, peerb peer.CwtchPeer) {
  73. for {
  74. //peers := peera.GetPeers()
  75. _, ok := peera.GetProfile().Contacts[peerb.GetProfile().Onion]
  76. if ok {
  77. state := peera.GetPeerState(peerb.GetProfile().Onion)
  78. //log.Infof("Waiting for Peer %v to peer with peer: %v - state: %v\n", peera.GetProfile().Name, peerb.GetProfile().Name, state)
  79. if state == connections.FAILED {
  80. t.Fatalf("%v could not connect to %v", peera.GetProfile().Onion, peerb.GetProfile().Onion)
  81. }
  82. if state != connections.AUTHENTICATED {
  83. fmt.Printf("peer% v waiting connect to peer %v, currently: %v\n", peera.GetProfile().Onion, peerb.GetProfile().Onion, connections.ConnectionStateName[state])
  84. time.Sleep(time.Second * 5)
  85. continue
  86. } else {
  87. break
  88. }
  89. } // It might take a second for the peer to show up as it is now going through the event bus
  90. time.Sleep(time.Second)
  91. }
  92. return
  93. }
  94. func waitGetPeer(app app2.Application, name string) peer.CwtchPeer {
  95. for true {
  96. for id, n := range app.ListPeers() {
  97. if n == name {
  98. return app.GetPeer(id)
  99. }
  100. }
  101. time.Sleep(100 * time.Millisecond)
  102. }
  103. return nil
  104. }
  105. func TestCwtchPeerIntegration(t *testing.T) {
  106. numGoRoutinesStart := runtime.NumGoroutine()
  107. log.AddEverythingFromPattern("connectivity")
  108. //log.SetLevel(log.LevelDebug)
  109. acn, err := connectivity.StartTor(".", "")
  110. if err != nil {
  111. t.Fatalf("Could not start Tor: %v", err)
  112. }
  113. // ***** Cwtch Server management *****
  114. var server *cwtchserver.Server
  115. serverOnline := false
  116. var serverAddr string
  117. if !serverOnline {
  118. // launch app with new key
  119. fmt.Println("No server found!")
  120. server = new(cwtchserver.Server)
  121. fmt.Println("Starting cwtch server...")
  122. os.Remove("server-test.json")
  123. config := cwtchserver.LoadConfig(".", "server-test.json")
  124. identity := config.Identity()
  125. serverAddr = identity.Hostname()
  126. go server.Run(acn, config)
  127. // let tor get established
  128. fmt.Printf("Establishing Tor hidden service: %v...\n", serverAddr)
  129. } else {
  130. fmt.Printf("Found existing cwtch server %v, using for tests...\n", serverAddr)
  131. }
  132. numGoRoutinesPostServer := runtime.NumGoroutine()
  133. app := app2.NewApp(acn, "./storage")
  134. bridge1, bridge2 := event.MakePipeBridge()
  135. appClient := app2.NewAppClient(acn, "./storage", bridge1)
  136. appService := app2.NewAppService(acn, "./storage", bridge2)
  137. numGoRoutinesPostAppStart := runtime.NumGoroutine()
  138. // ***** cwtchPeer setup *****
  139. fmt.Println("Creating Alice...")
  140. app.CreatePeer("alice", "asdfasdf")
  141. fmt.Println("Creating Bob...")
  142. app.CreatePeer("bob", "asdfasdf")
  143. fmt.Println("Creating Carol...")
  144. appClient.CreatePeer("carol", "asdfasdf")
  145. alice := waitGetPeer(app, "alice")
  146. fmt.Println("Alice created:", alice.GetProfile().Onion)
  147. bob := waitGetPeer(app, "bob")
  148. fmt.Println("Bob created:", bob.GetProfile().Onion)
  149. carol := waitGetPeer(appClient, "carol")
  150. fmt.Println("Carol created:", carol.GetProfile().Onion)
  151. //fmt.Println("Carol created:", carol.GetProfile().Onion)
  152. app.LaunchPeers()
  153. appClient.LaunchPeers()
  154. fmt.Println("Waiting for Alice, Bob, and Carol to connect with onion network...")
  155. time.Sleep(time.Second * 90)
  156. numGoRoutinesPostPeerStart := runtime.NumGoroutine()
  157. // ***** Peering, server joining, group creation / invite *****
  158. fmt.Println("Creating group on ", serverAddr, "...")
  159. groupID, _, err := alice.StartGroup(serverAddr)
  160. fmt.Printf("Created group: %v!\n", groupID)
  161. if err != nil {
  162. t.Errorf("Failed to init group: %v", err)
  163. return
  164. }
  165. fmt.Println("Alice peering with Bob...")
  166. alice.AddContact("Bob", bob.GetProfile().Onion, false) // Add contact so we can track connection state
  167. alice.PeerWithOnion(bob.GetProfile().Onion)
  168. fmt.Println("Alice peering with Carol...")
  169. alice.AddContact("Carol", carol.GetProfile().Onion, false)
  170. alice.PeerWithOnion(carol.GetProfile().Onion)
  171. fmt.Println("Alice joining server...")
  172. alice.JoinServer(serverAddr)
  173. fmt.Println("Bob joining server...")
  174. bob.JoinServer(serverAddr)
  175. fmt.Println("Waiting for alice to join server...")
  176. waitForPeerGroupConnection(t, alice, groupID)
  177. //fmt.Println("Waiting for bob to join server...")
  178. //waitForPeerGroupConnection(t, bob, groupID)
  179. fmt.Println("Waiting for alice and Bob to peer...")
  180. waitForPeerPeerConnection(t, alice, bob)
  181. /*fmt.Println("Waiting for peerings and server joins...")
  182. time.Sleep(time.Second * 240)*/
  183. fmt.Println("Alice inviting Bob to group...")
  184. err = alice.InviteOnionToGroup(bob.GetProfile().Onion, groupID)
  185. if err != nil {
  186. t.Fatalf("Error for Alice inviting Bob to group: %v", err)
  187. }
  188. time.Sleep(time.Second * 10)
  189. fmt.Println("Bob examining groups and accepting invites...")
  190. for _, groupID := range bob.GetGroups() {
  191. group := bob.GetGroup(groupID)
  192. fmt.Printf("Bob group: %v (Accepted: %v)\n", group.GroupID, group.Accepted)
  193. if group.Accepted == false {
  194. fmt.Printf("Bob received and accepting group invite: %v\n", group.GroupID)
  195. bob.AcceptInvite(group.GroupID)
  196. }
  197. }
  198. time.Sleep(time.Second * 5)
  199. numGoRoutinesPostServerConnect := runtime.NumGoroutine()
  200. // Wait for them to join the server
  201. waitForPeerGroupConnection(t, alice, groupID)
  202. waitForPeerGroupConnection(t, bob, groupID)
  203. //numGouRoutinesPostServerConnect := runtime.NumGoroutine()
  204. // ***** Conversation *****
  205. fmt.Println("Starting conversation in group...")
  206. // Conversation
  207. fmt.Println("Alice> ", aliceLines[0])
  208. err = alice.SendMessageToGroup(groupID, aliceLines[0])
  209. if err != nil {
  210. t.Fatalf("Alice failed to send a message to the group: %v", err)
  211. }
  212. time.Sleep(time.Second * 10)
  213. fmt.Println("Bob> ", bobLines[0])
  214. err = bob.SendMessageToGroup(groupID, bobLines[0])
  215. if err != nil {
  216. t.Fatalf("Bob failed to send a message to the group: %v", err)
  217. }
  218. time.Sleep(time.Second * 10)
  219. fmt.Println("Alice> ", aliceLines[1])
  220. alice.SendMessageToGroup(groupID, aliceLines[1])
  221. time.Sleep(time.Second * 10)
  222. fmt.Println("Bob> ", bobLines[1])
  223. bob.SendMessageToGroup(groupID, bobLines[1])
  224. time.Sleep(time.Second * 10)
  225. fmt.Println("Alice inviting Carol to group...")
  226. err = alice.InviteOnionToGroup(carol.GetProfile().Onion, groupID)
  227. if err != nil {
  228. t.Fatalf("Error for Alice inviting Carol to group: %v", err)
  229. }
  230. time.Sleep(time.Second * 10)
  231. fmt.Println("Carol examining groups and accepting invites...")
  232. for _, groupID := range carol.GetGroups() {
  233. group := carol.GetGroup(groupID)
  234. fmt.Printf("Carol group: %v (Accepted: %v)\n", group.GroupID, group.Accepted)
  235. if group.Accepted == false {
  236. fmt.Printf("Carol received and accepting group invite: %v\n", group.GroupID)
  237. carol.AcceptInvite(group.GroupID)
  238. }
  239. }
  240. fmt.Println("Shutting down Alice...")
  241. app.ShutdownPeer(alice.GetProfile().Onion)
  242. time.Sleep(time.Second * 5)
  243. numGoRoutinesPostAlice := runtime.NumGoroutine()
  244. fmt.Println("Carol joining server...")
  245. carol.JoinServer(serverAddr)
  246. waitForPeerGroupConnection(t, carol, groupID)
  247. numGoRotinesPostCarolConnect := runtime.NumGoroutine()
  248. fmt.Println("Bob> ", bobLines[2])
  249. bob.SendMessageToGroup(groupID, bobLines[2])
  250. time.Sleep(time.Second * 10)
  251. fmt.Println("Carol> ", carolLines[0])
  252. carol.SendMessageToGroup(groupID, carolLines[0])
  253. time.Sleep(time.Second * 10)
  254. // ***** Verify Test *****
  255. fmt.Println("Final syncing time...")
  256. time.Sleep(time.Second * 30)
  257. alicesGroup := alice.GetGroup(groupID)
  258. if alicesGroup == nil {
  259. t.Error("aliceGroup == nil")
  260. return
  261. }
  262. fmt.Printf("Alice's TimeLine:\n")
  263. aliceVerified := printAndCountVerifedTimeline(t, alicesGroup.GetTimeline())
  264. if aliceVerified != 4 {
  265. t.Errorf("Alice did not have 4 verified messages")
  266. }
  267. bobsGroup := bob.GetGroup(groupID)
  268. if bobsGroup == nil {
  269. t.Error("bobGroup == nil")
  270. return
  271. }
  272. fmt.Printf("Bob's TimeLine:\n")
  273. bobVerified := printAndCountVerifedTimeline(t, bobsGroup.GetTimeline())
  274. if bobVerified != 6 {
  275. t.Errorf("Bob did not have 5 verified messages")
  276. }
  277. carolsGroup := carol.GetGroup(groupID)
  278. fmt.Printf("Carol's TimeLine:\n")
  279. carolVerified := printAndCountVerifedTimeline(t, carolsGroup.GetTimeline())
  280. if carolVerified != 6 {
  281. t.Errorf("Carol did not have 3 verified messages")
  282. }
  283. if len(alicesGroup.GetTimeline()) != 4 {
  284. t.Errorf("Alice's timeline does not have all messages")
  285. } else {
  286. // check message 0,1,2,3
  287. aliceGroupTimeline := alicesGroup.GetTimeline()
  288. if aliceGroupTimeline[0].Message != aliceLines[0] || aliceGroupTimeline[1].Message != bobLines[0] ||
  289. aliceGroupTimeline[2].Message != aliceLines[1] || aliceGroupTimeline[3].Message != bobLines[1] {
  290. t.Errorf("Some of Alice's timeline messages did not have the expected content!")
  291. }
  292. }
  293. if len(bobsGroup.GetTimeline()) != 6 {
  294. t.Errorf("Bob's timeline does not have all messages")
  295. } else {
  296. // check message 0,1,2,3,4,5
  297. bobGroupTimeline := bobsGroup.GetTimeline()
  298. if bobGroupTimeline[0].Message != aliceLines[0] || bobGroupTimeline[1].Message != bobLines[0] ||
  299. bobGroupTimeline[2].Message != aliceLines[1] || bobGroupTimeline[3].Message != bobLines[1] ||
  300. bobGroupTimeline[4].Message != bobLines[2] || bobGroupTimeline[5].Message != carolLines[0] {
  301. t.Errorf("Some of Bob's timeline messages did not have the expected content!")
  302. }
  303. }
  304. if len(carolsGroup.GetTimeline()) != 6 {
  305. t.Errorf("Carol's timeline does not have all messages")
  306. } else {
  307. // check message 0,1,2,3,4,5
  308. carolGroupTimeline := carolsGroup.GetTimeline()
  309. if carolGroupTimeline[0].Message != aliceLines[0] || carolGroupTimeline[1].Message != bobLines[0] ||
  310. carolGroupTimeline[2].Message != aliceLines[1] || carolGroupTimeline[3].Message != bobLines[1] ||
  311. carolGroupTimeline[4].Message != bobLines[2] || carolGroupTimeline[5].Message != carolLines[0] {
  312. t.Errorf("Some of Carol's timeline messages did not have the expected content!")
  313. }
  314. }
  315. fmt.Println("Shutting down Bob...")
  316. app.ShutdownPeer(bob.GetProfile().Onion)
  317. time.Sleep(time.Second * 3)
  318. numGoRoutinesPostBob := runtime.NumGoroutine()
  319. if server != nil {
  320. fmt.Println("Shutting down server...")
  321. server.Shutdown()
  322. time.Sleep(time.Second * 3)
  323. }
  324. numGoRoutinesPostServerShutdown := runtime.NumGoroutine()
  325. fmt.Println("Shutting down Carol...")
  326. appClient.ShutdownPeer(carol.GetProfile().Onion)
  327. time.Sleep(time.Second * 3)
  328. numGoRoutinesPostCarol := runtime.NumGoroutine()
  329. fmt.Println("Shutting down apps...")
  330. app.Shutdown()
  331. appClient.Shutdown()
  332. appService.Shutdown()
  333. bridge1.Shutdown()
  334. bridge2.Shutdown()
  335. numGoRoutinesPostAppShutdown := runtime.NumGoroutine()
  336. fmt.Println("Shutting down ACN...")
  337. acn.Close()
  338. time.Sleep(time.Second * 2) // Server ^^ has a 5 second loop attempting reconnect before exiting
  339. numGoRoutinesPostACN := runtime.NumGoroutine()
  340. // Printing out the current goroutines
  341. // Very useful if we are leaking any.
  342. pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
  343. fmt.Printf("numGoRoutinesStart: %v\nnumGoRoutinesPostServer: %v\nnumGoRoutinesPostAppStart: %v\nnumGoRoutinesPostPeerStart: %v\nnumGoRoutinesPostPeerAndServerConnect: %v\n"+
  344. "numGoRoutinesPostAlice: %v\nnumGoRotinesPostCarolConnect: %v\nnumGoRoutinesPostBob: %v\nnumGoRoutinesPostServerShutdown: %v\nnumGoRoutinesPostCarol: %v\nnumGoRoutinesPostAppShutdown: %v\nnumGoRoutinesPostACN: %v\n",
  345. numGoRoutinesStart, numGoRoutinesPostServer, numGoRoutinesPostAppStart, numGoRoutinesPostPeerStart, numGoRoutinesPostServerConnect,
  346. numGoRoutinesPostAlice, numGoRotinesPostCarolConnect, numGoRoutinesPostBob, numGoRoutinesPostServerShutdown, numGoRoutinesPostCarol, numGoRoutinesPostAppShutdown, numGoRoutinesPostACN)
  347. if numGoRoutinesStart != numGoRoutinesPostACN {
  348. t.Errorf("Number of GoRoutines at start (%v) does not match number of goRoutines after cleanup of peers and servers (%v), clean up failed, leak detected!", numGoRoutinesStart, numGoRoutinesPostACN)
  349. }
  350. }