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.

426 lines
14KB

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