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.
 
 
 
 

472 lines
16 KiB

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