serve_test.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. package main
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/flashmob/go-guerrilla"
  7. "github.com/flashmob/go-guerrilla/backends"
  8. "github.com/flashmob/go-guerrilla/log"
  9. test "github.com/flashmob/go-guerrilla/tests"
  10. "github.com/flashmob/go-guerrilla/tests/testcert"
  11. "github.com/spf13/cobra"
  12. "io/ioutil"
  13. "os"
  14. "os/exec"
  15. "runtime"
  16. "strconv"
  17. "strings"
  18. "sync"
  19. "testing"
  20. "time"
  21. )
  22. var configJsonA = `
  23. {
  24. "log_file" : "../../tests/testlog",
  25. "log_level" : "debug",
  26. "pid_file" : "./pidfile.pid",
  27. "allowed_hosts": [
  28. "guerrillamail.com",
  29. "guerrillamailblock.com",
  30. "sharklasers.com",
  31. "guerrillamail.net",
  32. "guerrillamail.org"
  33. ],
  34. "backend_name": "dummy",
  35. "backend_config": {
  36. "log_received_mails": true
  37. },
  38. "servers" : [
  39. {
  40. "is_enabled" : true,
  41. "host_name":"mail.test.com",
  42. "max_size": 1000000,
  43. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  44. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  45. "timeout":180,
  46. "listen_interface":"127.0.0.1:25",
  47. "start_tls_on":true,
  48. "tls_always_on":false,
  49. "max_clients": 1000,
  50. "log_file" : "../../tests/testlog"
  51. },
  52. {
  53. "is_enabled" : false,
  54. "host_name":"enable.test.com",
  55. "max_size": 1000000,
  56. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  57. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  58. "timeout":180,
  59. "listen_interface":"127.0.0.1:2228",
  60. "start_tls_on":true,
  61. "tls_always_on":false,
  62. "max_clients": 1000,
  63. "log_file" : "../../tests/testlog"
  64. }
  65. ]
  66. }
  67. `
  68. // backend config changed, log_received_mails is false
  69. var configJsonB = `
  70. {
  71. "log_file" : "../../tests/testlog",
  72. "log_level" : "debug",
  73. "pid_file" : "./pidfile2.pid",
  74. "allowed_hosts": [
  75. "guerrillamail.com",
  76. "guerrillamailblock.com",
  77. "sharklasers.com",
  78. "guerrillamail.net",
  79. "guerrillamail.org"
  80. ],
  81. "backend_name": "dummy",
  82. "backend_config": {
  83. "log_received_mails": false
  84. },
  85. "servers" : [
  86. {
  87. "is_enabled" : true,
  88. "host_name":"mail.test.com",
  89. "max_size": 1000000,
  90. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  91. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  92. "timeout":180,
  93. "listen_interface":"127.0.0.1:25",
  94. "start_tls_on":true,
  95. "tls_always_on":false,
  96. "max_clients": 1000,
  97. "log_file" : "../../tests/testlog"
  98. }
  99. ]
  100. }
  101. `
  102. // backend_name changed, is guerrilla-redis-db + added a server
  103. var configJsonC = `
  104. {
  105. "log_file" : "../../tests/testlog",
  106. "log_level" : "debug",
  107. "pid_file" : "./pidfile.pid",
  108. "allowed_hosts": [
  109. "guerrillamail.com",
  110. "guerrillamailblock.com",
  111. "sharklasers.com",
  112. "guerrillamail.net",
  113. "guerrillamail.org"
  114. ],
  115. "backend_name": "guerrilla-redis-db",
  116. "backend_config" :
  117. {
  118. "mysql_db":"gmail_mail",
  119. "mysql_host":"127.0.0.1:3306",
  120. "mysql_pass":"ok",
  121. "mysql_user":"root",
  122. "mail_table":"new_mail",
  123. "redis_interface" : "127.0.0.1:6379",
  124. "redis_expire_seconds" : 7200,
  125. "save_workers_size" : 3,
  126. "primary_mail_host":"sharklasers.com"
  127. },
  128. "servers" : [
  129. {
  130. "is_enabled" : true,
  131. "host_name":"mail.test.com",
  132. "max_size": 1000000,
  133. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  134. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  135. "timeout":180,
  136. "listen_interface":"127.0.0.1:25",
  137. "start_tls_on":true,
  138. "tls_always_on":false,
  139. "max_clients": 1000,
  140. "log_file" : "../../tests/testlog"
  141. },
  142. {
  143. "is_enabled" : true,
  144. "host_name":"mail.test.com",
  145. "max_size":1000000,
  146. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  147. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  148. "timeout":180,
  149. "listen_interface":"127.0.0.1:465",
  150. "start_tls_on":false,
  151. "tls_always_on":true,
  152. "max_clients":500,
  153. "log_file" : "../../tests/testlog"
  154. }
  155. ]
  156. }
  157. `
  158. // adds 127.0.0.1:4655, a secure server
  159. var configJsonD = `
  160. {
  161. "log_file" : "../../tests/testlog",
  162. "log_level" : "debug",
  163. "pid_file" : "./pidfile.pid",
  164. "allowed_hosts": [
  165. "guerrillamail.com",
  166. "guerrillamailblock.com",
  167. "sharklasers.com",
  168. "guerrillamail.net",
  169. "guerrillamail.org"
  170. ],
  171. "backend_name": "dummy",
  172. "backend_config": {
  173. "log_received_mails": false
  174. },
  175. "servers" : [
  176. {
  177. "is_enabled" : true,
  178. "host_name":"mail.test.com",
  179. "max_size": 1000000,
  180. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  181. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  182. "timeout":180,
  183. "listen_interface":"127.0.0.1:2552",
  184. "start_tls_on":true,
  185. "tls_always_on":false,
  186. "max_clients": 1000,
  187. "log_file" : "../../tests/testlog"
  188. },
  189. {
  190. "is_enabled" : true,
  191. "host_name":"secure.test.com",
  192. "max_size":1000000,
  193. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  194. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  195. "timeout":180,
  196. "listen_interface":"127.0.0.1:4655",
  197. "start_tls_on":false,
  198. "tls_always_on":true,
  199. "max_clients":500,
  200. "log_file" : "../../tests/testlog"
  201. }
  202. ]
  203. }
  204. `
  205. const testPauseDuration = time.Millisecond * 600
  206. // reload config
  207. func sigHup() {
  208. if data, err := ioutil.ReadFile("pidfile.pid"); err == nil {
  209. mainlog.Infof("pid read is %s", data)
  210. ecmd := exec.Command("kill", "-HUP", string(data))
  211. _, err = ecmd.Output()
  212. if err != nil {
  213. mainlog.Infof("could not SIGHUP", err)
  214. }
  215. } else {
  216. mainlog.WithError(err).Info("sighup - Could not read pidfle")
  217. }
  218. }
  219. // shutdown after calling serve()
  220. func sigKill() {
  221. if data, err := ioutil.ReadFile("pidfile.pid"); err == nil {
  222. mainlog.Infof("pid read is %s", data)
  223. ecmd := exec.Command("kill", string(data))
  224. _, err = ecmd.Output()
  225. if err != nil {
  226. mainlog.Infof("could not sigkill", err)
  227. }
  228. } else {
  229. mainlog.WithError(err).Info("sigKill - Could not read pidfle")
  230. }
  231. }
  232. // make sure that we get all the config change events
  233. func TestCmdConfigChangeEvents(t *testing.T) {
  234. oldconf := &CmdConfig{}
  235. oldconf.load([]byte(configJsonA))
  236. newconf := &CmdConfig{}
  237. newconf.load([]byte(configJsonB))
  238. newerconf := &CmdConfig{}
  239. newerconf.load([]byte(configJsonC))
  240. expectedEvents := map[guerrilla.Event]bool{
  241. guerrilla.EvConfigBackendConfig: false,
  242. guerrilla.EvConfigBackendName: false,
  243. guerrilla.EvConfigEvServerNew: false,
  244. }
  245. mainlog, _ = log.GetLogger("off")
  246. bcfg := backends.BackendConfig{"log_received_mails": true}
  247. backend, err := backends.New("dummy", bcfg, mainlog)
  248. app, err := guerrilla.New(&oldconf.AppConfig, backend, mainlog)
  249. if err != nil {
  250. //log.Info("Failed to create new app", err)
  251. }
  252. toUnsubscribe := map[guerrilla.Event]func(c *CmdConfig){}
  253. toUnsubscribeS := map[guerrilla.Event]func(c *guerrilla.ServerConfig){}
  254. for event := range expectedEvents {
  255. // Put in anon func since range is overwriting event
  256. func(e guerrilla.Event) {
  257. if strings.Index(e.String(), "server_change") == 0 {
  258. f := func(c *guerrilla.ServerConfig) {
  259. expectedEvents[e] = true
  260. }
  261. app.Subscribe(event, f)
  262. toUnsubscribeS[event] = f
  263. } else {
  264. f := func(c *CmdConfig) {
  265. expectedEvents[e] = true
  266. }
  267. app.Subscribe(event, f)
  268. toUnsubscribe[event] = f
  269. }
  270. }(event)
  271. }
  272. // emit events
  273. newconf.emitChangeEvents(oldconf, app)
  274. newerconf.emitChangeEvents(newconf, app)
  275. // unsubscribe
  276. for unevent, unfun := range toUnsubscribe {
  277. app.Unsubscribe(unevent, unfun)
  278. }
  279. for event, val := range expectedEvents {
  280. if val == false {
  281. t.Error("Did not fire config change event:", event)
  282. t.FailNow()
  283. break
  284. }
  285. }
  286. // cleanup
  287. os.Truncate("../../tests/testlog", 0)
  288. }
  289. // start server, change config, send SIG HUP, confirm that the pidfile changed & backend reloaded
  290. func TestServe(t *testing.T) {
  291. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  292. mainlog, _ = log.GetLogger("../../tests/testlog")
  293. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  294. cmd := &cobra.Command{}
  295. configPath = "configJsonA.json"
  296. var serveWG sync.WaitGroup
  297. serveWG.Add(1)
  298. go func() {
  299. serve(cmd, []string{})
  300. serveWG.Done()
  301. }()
  302. time.Sleep(testPauseDuration)
  303. data, err := ioutil.ReadFile("pidfile.pid")
  304. if err != nil {
  305. t.Error("error reading pidfile.pid", err)
  306. t.FailNow()
  307. }
  308. _, err = strconv.Atoi(string(data))
  309. if err != nil {
  310. t.Error("could not parse pidfile.pid", err)
  311. t.FailNow()
  312. }
  313. // change the config file
  314. ioutil.WriteFile("configJsonA.json", []byte(configJsonB), 0644)
  315. // test SIGHUP via the kill command
  316. // Would not work on windows as kill is not available.
  317. // TODO: Implement an alternative test for windows.
  318. if runtime.GOOS != "windows" {
  319. ecmd := exec.Command("kill", "-HUP", string(data))
  320. _, err = ecmd.Output()
  321. if err != nil {
  322. t.Error("could not SIGHUP", err)
  323. t.FailNow()
  324. }
  325. time.Sleep(testPauseDuration) // allow sighup to do its job
  326. // did the pidfile change as expected?
  327. if _, err := os.Stat("./pidfile2.pid"); os.IsNotExist(err) {
  328. t.Error("pidfile not changed after sighup SIGHUP", err)
  329. }
  330. }
  331. // send kill signal and wait for exit
  332. sigKill()
  333. serveWG.Wait()
  334. // did backend started as expected?
  335. fd, err := os.Open("../../tests/testlog")
  336. if err != nil {
  337. t.Error(err)
  338. }
  339. if read, err := ioutil.ReadAll(fd); err == nil {
  340. logOutput := string(read)
  341. if i := strings.Index(logOutput, "Backend started:dummy"); i < 0 {
  342. t.Error("Dummy backend not restared")
  343. }
  344. }
  345. // cleanup
  346. os.Truncate("../../tests/testlog", 0)
  347. os.Remove("configJsonA.json")
  348. os.Remove("./pidfile.pid")
  349. os.Remove("./pidfile2.pid")
  350. }
  351. // Start with configJsonA.json,
  352. // then add a new server to it (127.0.0.1:2526),
  353. // then SIGHUP (to reload config & trigger config update events),
  354. // then connect to it & HELO.
  355. func TestServerAddEvent(t *testing.T) {
  356. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  357. mainlog, _ = log.GetLogger("../../tests/testlog")
  358. // start the server by emulating the serve command
  359. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  360. cmd := &cobra.Command{}
  361. configPath = "configJsonA.json"
  362. var serveWG sync.WaitGroup
  363. serveWG.Add(1)
  364. go func() {
  365. serve(cmd, []string{})
  366. serveWG.Done()
  367. }()
  368. time.Sleep(testPauseDuration) // allow the server to start
  369. // now change the config by adding a server
  370. conf := &CmdConfig{} // blank one
  371. conf.load([]byte(configJsonA)) // load configJsonA
  372. newServer := conf.Servers[0] // copy the first server config
  373. newServer.ListenInterface = "127.0.0.1:2526" // change it
  374. newConf := conf // copy the cmdConfg
  375. newConf.Servers = append(newConf.Servers, newServer) // add the new server
  376. if jsonbytes, err := json.Marshal(newConf); err == nil {
  377. //fmt.Println(string(jsonbytes))
  378. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  379. }
  380. // send a sighup signal to the server
  381. sigHup()
  382. time.Sleep(testPauseDuration) // pause for config to reload
  383. if conn, buffin, err := test.Connect(newServer, 20); err != nil {
  384. t.Error("Could not connect to new server", newServer.ListenInterface)
  385. } else {
  386. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  387. expect := "250 mail.test.com Hello"
  388. if strings.Index(result, expect) != 0 {
  389. t.Error("Expected", expect, "but got", result)
  390. }
  391. } else {
  392. t.Error(err)
  393. }
  394. }
  395. // send kill signal and wait for exit
  396. sigKill()
  397. serveWG.Wait()
  398. // did backend started as expected?
  399. fd, _ := os.Open("../../tests/testlog")
  400. if read, err := ioutil.ReadAll(fd); err == nil {
  401. logOutput := string(read)
  402. //fmt.Println(logOutput)
  403. if i := strings.Index(logOutput, "New server added [127.0.0.1:2526]"); i < 0 {
  404. t.Error("Did not add [127.0.0.1:2526], most likely because Bus.Subscribe(\"server_change:new_server\" didnt fire")
  405. }
  406. }
  407. // cleanup
  408. os.Truncate("../../tests/testlog", 0)
  409. os.Remove("configJsonA.json")
  410. os.Remove("./pidfile.pid")
  411. }
  412. // Start with configJsonA.json,
  413. // then change the config to enable 127.0.0.1:2228,
  414. // then write the new config,
  415. // then SIGHUP (to reload config & trigger config update events),
  416. // then connect to 127.0.0.1:2228 & HELO.
  417. func TestServerStartEvent(t *testing.T) {
  418. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  419. mainlog, _ = log.GetLogger("../../tests/testlog")
  420. // start the server by emulating the serve command
  421. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  422. cmd := &cobra.Command{}
  423. configPath = "configJsonA.json"
  424. var serveWG sync.WaitGroup
  425. serveWG.Add(1)
  426. go func() {
  427. serve(cmd, []string{})
  428. serveWG.Done()
  429. }()
  430. time.Sleep(testPauseDuration)
  431. // now change the config by adding a server
  432. conf := &CmdConfig{} // blank one
  433. conf.load([]byte(configJsonA)) // load configJsonA
  434. newConf := conf // copy the cmdConfg
  435. newConf.Servers[1].IsEnabled = true
  436. if jsonbytes, err := json.Marshal(newConf); err == nil {
  437. //fmt.Println(string(jsonbytes))
  438. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  439. } else {
  440. t.Error(err)
  441. }
  442. // send a sighup signal to the server
  443. sigHup()
  444. time.Sleep(testPauseDuration) // pause for config to reload
  445. if conn, buffin, err := test.Connect(newConf.Servers[1], 20); err != nil {
  446. t.Error("Could not connect to new server", newConf.Servers[1].ListenInterface)
  447. } else {
  448. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  449. expect := "250 enable.test.com Hello"
  450. if strings.Index(result, expect) != 0 {
  451. t.Error("Expected", expect, "but got", result)
  452. }
  453. } else {
  454. t.Error(err)
  455. }
  456. }
  457. // send kill signal and wait for exit
  458. sigKill()
  459. serveWG.Wait()
  460. // did backend started as expected?
  461. fd, _ := os.Open("../../tests/testlog")
  462. if read, err := ioutil.ReadAll(fd); err == nil {
  463. logOutput := string(read)
  464. //fmt.Println(logOutput)
  465. if i := strings.Index(logOutput, "Starting server [127.0.0.1:2228]"); i < 0 {
  466. t.Error("did not add [127.0.0.1:2228], most likely because Bus.Subscribe(\"server_change:start_server\" didnt fire")
  467. }
  468. }
  469. // cleanup
  470. os.Truncate("../../tests/testlog", 0)
  471. os.Remove("configJsonA.json")
  472. os.Remove("./pidfile.pid")
  473. }
  474. // Start with configJsonA.json,
  475. // then change the config to enable 127.0.0.1:2228,
  476. // then write the new config,
  477. // then SIGHUP (to reload config & trigger config update events),
  478. // then connect to 127.0.0.1:2228 & HELO.
  479. // then change the config to dsiable 127.0.0.1:2228,
  480. // then SIGHUP (to reload config & trigger config update events),
  481. // then connect to 127.0.0.1:2228 - it should not connect
  482. func TestServerStopEvent(t *testing.T) {
  483. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  484. mainlog, _ = log.GetLogger("../../tests/testlog")
  485. // start the server by emulating the serve command
  486. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  487. cmd := &cobra.Command{}
  488. configPath = "configJsonA.json"
  489. var serveWG sync.WaitGroup
  490. serveWG.Add(1)
  491. go func() {
  492. serve(cmd, []string{})
  493. serveWG.Done()
  494. }()
  495. time.Sleep(testPauseDuration)
  496. // now change the config by enabling a server
  497. conf := &CmdConfig{} // blank one
  498. conf.load([]byte(configJsonA)) // load configJsonA
  499. newConf := conf // copy the cmdConfg
  500. newConf.Servers[1].IsEnabled = true
  501. if jsonbytes, err := json.Marshal(newConf); err == nil {
  502. //fmt.Println(string(jsonbytes))
  503. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  504. } else {
  505. t.Error(err)
  506. }
  507. // send a sighup signal to the server
  508. sigHup()
  509. time.Sleep(testPauseDuration) // pause for config to reload
  510. if conn, buffin, err := test.Connect(newConf.Servers[1], 20); err != nil {
  511. t.Error("Could not connect to new server", newConf.Servers[1].ListenInterface)
  512. } else {
  513. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  514. expect := "250 enable.test.com Hello"
  515. if strings.Index(result, expect) != 0 {
  516. t.Error("Expected", expect, "but got", result)
  517. }
  518. } else {
  519. t.Error(err)
  520. }
  521. conn.Close()
  522. }
  523. // now disable the server
  524. newerConf := newConf // copy the cmdConfg
  525. newerConf.Servers[1].IsEnabled = false
  526. if jsonbytes, err := json.Marshal(newerConf); err == nil {
  527. //fmt.Println(string(jsonbytes))
  528. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  529. } else {
  530. t.Error(err)
  531. }
  532. // send a sighup signal to the server
  533. sigHup()
  534. time.Sleep(testPauseDuration) // pause for config to reload
  535. // it should not connect to the server
  536. if _, _, err := test.Connect(newConf.Servers[1], 20); err == nil {
  537. t.Error("127.0.0.1:2228 was disabled, but still accepting connections", newConf.Servers[1].ListenInterface)
  538. }
  539. // send kill signal and wait for exit
  540. sigKill()
  541. serveWG.Wait()
  542. // did backend started as expected?
  543. fd, _ := os.Open("../../tests/testlog")
  544. if read, err := ioutil.ReadAll(fd); err == nil {
  545. logOutput := string(read)
  546. //fmt.Println(logOutput)
  547. if i := strings.Index(logOutput, "Server [127.0.0.1:2228] stopped"); i < 0 {
  548. t.Error("did not stop [127.0.0.1:2228], most likely because Bus.Subscribe(\"server_change:stop_server\" didnt fire")
  549. }
  550. }
  551. // cleanup
  552. os.Truncate("../../tests/testlog", 0)
  553. os.Remove("configJsonA.json")
  554. os.Remove("./pidfile.pid")
  555. }
  556. // Start with configJsonD.json,
  557. // then connect to 127.0.0.1:4655 & HELO & try RCPT TO with an invalid host [grr.la]
  558. // then change the config to enable add new host [grr.la] to allowed_hosts
  559. // then write the new config,
  560. // then SIGHUP (to reload config & trigger config update events),
  561. // connect to 127.0.0.1:4655 & HELO & try RCPT TO, grr.la should work
  562. func TestAllowedHostsEvent(t *testing.T) {
  563. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  564. mainlog, _ = log.GetLogger("../../tests/testlog")
  565. // start the server by emulating the serve command
  566. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  567. conf := &CmdConfig{} // blank one
  568. conf.load([]byte(configJsonD)) // load configJsonD
  569. cmd := &cobra.Command{}
  570. configPath = "configJsonD.json"
  571. var serveWG sync.WaitGroup
  572. time.Sleep(testPauseDuration)
  573. serveWG.Add(1)
  574. go func() {
  575. serve(cmd, []string{})
  576. serveWG.Done()
  577. }()
  578. time.Sleep(testPauseDuration)
  579. // now connect and try RCPT TO with an invalid host
  580. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[1], 20); err != nil {
  581. t.Error("Could not connect to new server", conf.AppConfig.Servers[1].ListenInterface, err)
  582. } else {
  583. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  584. expect := "250 secure.test.com Hello"
  585. if strings.Index(result, expect) != 0 {
  586. t.Error("Expected", expect, "but got", result)
  587. } else {
  588. if result, err = test.Command(conn, buffin, "RCPT TO:[email protected]"); err == nil {
  589. expect := "454 4.1.1 Error: Relay access denied: grr.la"
  590. if strings.Index(result, expect) != 0 {
  591. t.Error("Expected:", expect, "but got:", result)
  592. }
  593. }
  594. }
  595. }
  596. conn.Close()
  597. }
  598. // now change the config by adding a host to allowed hosts
  599. newConf := conf // copy the cmdConfg
  600. newConf.AllowedHosts = append(newConf.AllowedHosts, "grr.la")
  601. if jsonbytes, err := json.Marshal(newConf); err == nil {
  602. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  603. } else {
  604. t.Error(err)
  605. }
  606. // send a sighup signal to the server to reload config
  607. sigHup()
  608. time.Sleep(testPauseDuration) // pause for config to reload
  609. // now repeat the same conversion, RCPT TO should be accepted
  610. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[1], 20); err != nil {
  611. t.Error("Could not connect to new server", conf.AppConfig.Servers[1].ListenInterface, err)
  612. } else {
  613. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  614. expect := "250 secure.test.com Hello"
  615. if strings.Index(result, expect) != 0 {
  616. t.Error("Expected", expect, "but got", result)
  617. } else {
  618. if result, err = test.Command(conn, buffin, "RCPT TO:[email protected]"); err == nil {
  619. expect := "250 2.1.5 OK"
  620. if strings.Index(result, expect) != 0 {
  621. t.Error("Expected:", expect, "but got:", result)
  622. }
  623. }
  624. }
  625. }
  626. conn.Close()
  627. }
  628. // send kill signal and wait for exit
  629. sigKill()
  630. serveWG.Wait()
  631. // did backend started as expected?
  632. fd, _ := os.Open("../../tests/testlog")
  633. if read, err := ioutil.ReadAll(fd); err == nil {
  634. logOutput := string(read)
  635. //fmt.Println(logOutput)
  636. if i := strings.Index(logOutput, "allowed_hosts config changed, a new list was set"); i < 0 {
  637. t.Errorf("did not change allowed_hosts, most likely because Bus.Subscribe(\"%s\" didnt fire",
  638. guerrilla.EvConfigAllowedHosts)
  639. }
  640. }
  641. // cleanup
  642. os.Truncate("../../tests/testlog", 0)
  643. os.Remove("configJsonD.json")
  644. os.Remove("./pidfile.pid")
  645. }
  646. // Test TLS config change event
  647. // start with configJsonD
  648. // should be able to STARTTLS to 127.0.0.1:2525 with no problems
  649. // generate new certs & reload config
  650. // should get a new tls event & able to STARTTLS with no problem
  651. func TestTLSConfigEvent(t *testing.T) {
  652. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  653. // pause for generated cert to output on slow machines
  654. time.Sleep(testPauseDuration)
  655. // did cert output?
  656. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  657. t.Error("Did not create cert ", err)
  658. }
  659. mainlog, _ = log.GetLogger("../../tests/testlog")
  660. // start the server by emulating the serve command
  661. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  662. conf := &CmdConfig{} // blank one
  663. conf.load([]byte(configJsonD)) // load configJsonD
  664. cmd := &cobra.Command{}
  665. configPath = "configJsonD.json"
  666. var serveWG sync.WaitGroup
  667. serveWG.Add(1)
  668. go func() {
  669. serve(cmd, []string{})
  670. serveWG.Done()
  671. }()
  672. time.Sleep(testPauseDuration)
  673. // Test STARTTLS handshake
  674. testTlsHandshake := func() {
  675. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  676. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  677. } else {
  678. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  679. expect := "250 mail.test.com Hello"
  680. if strings.Index(result, expect) != 0 {
  681. t.Error("Expected", expect, "but got", result)
  682. } else {
  683. if result, err = test.Command(conn, buffin, "STARTTLS"); err == nil {
  684. expect := "220 2.0.0 Ready to start TLS"
  685. if strings.Index(result, expect) != 0 {
  686. t.Error("Expected:", expect, "but got:", result)
  687. } else {
  688. tlsConn := tls.Client(conn, &tls.Config{
  689. InsecureSkipVerify: true,
  690. ServerName: "127.0.0.1",
  691. })
  692. if err := tlsConn.Handshake(); err != nil {
  693. t.Error("Failed to handshake", conf.AppConfig.Servers[0].ListenInterface)
  694. } else {
  695. conn = tlsConn
  696. mainlog.Info("TLS Handshake succeeded")
  697. }
  698. }
  699. }
  700. }
  701. }
  702. conn.Close()
  703. }
  704. }
  705. testTlsHandshake()
  706. if err := os.Remove("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  707. t.Error("could not remove cert", err)
  708. }
  709. if err := os.Remove("../../tests/mail2.guerrillamail.com.key.pem"); err != nil {
  710. t.Error("could not remove key", err)
  711. }
  712. // generate a new cert
  713. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  714. // pause for generated cert to output
  715. time.Sleep(testPauseDuration)
  716. // did cert output?
  717. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  718. t.Error("Did not create cert ", err)
  719. }
  720. sigHup()
  721. time.Sleep(testPauseDuration * 2) // pause for config to reload
  722. testTlsHandshake()
  723. //time.Sleep(testPauseDuration)
  724. // send kill signal and wait for exit
  725. sigKill()
  726. serveWG.Wait()
  727. // did backend started as expected?
  728. fd, _ := os.Open("../../tests/testlog")
  729. if read, err := ioutil.ReadAll(fd); err == nil {
  730. logOutput := string(read)
  731. //fmt.Println(logOutput)
  732. if i := strings.Index(logOutput, "Server [127.0.0.1:2552] new TLS configuration loaded"); i < 0 {
  733. t.Error("did not change tls, most likely because Bus.Subscribe(\"server_change:tls_config\" didnt fire")
  734. }
  735. }
  736. // cleanup
  737. os.Truncate("../../tests/testlog", 0)
  738. os.Remove("configJsonD.json")
  739. os.Remove("./pidfile.pid")
  740. }
  741. // Testing starting a server with a bad TLS config
  742. // It should not start, return exit code 1
  743. func TestBadTLSStart(t *testing.T) {
  744. // Need to run the test in a different process by executing a command
  745. // because the serve() does os.Exit when starting with a bad TLS config
  746. if os.Getenv("BE_CRASHER") == "1" {
  747. // do the test
  748. // first, remove the good certs, if any
  749. if err := os.Remove("./../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  750. mainlog.WithError(err).Error("could not remove ./../../tests/mail2.guerrillamail.com.cert.pem")
  751. } else {
  752. mainlog.Info("removed ./../../tests/mail2.guerrillamail.com.cert.pem")
  753. }
  754. // next run the server
  755. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  756. conf := &CmdConfig{} // blank one
  757. conf.load([]byte(configJsonD)) // load configJsonD
  758. cmd := &cobra.Command{}
  759. configPath = "configJsonD.json"
  760. var serveWG sync.WaitGroup
  761. serveWG.Add(1)
  762. go func() {
  763. serve(cmd, []string{})
  764. serveWG.Done()
  765. }()
  766. time.Sleep(testPauseDuration)
  767. sigKill()
  768. serveWG.Wait()
  769. return
  770. }
  771. cmd := exec.Command(os.Args[0], "-test.run=TestBadTLSStart")
  772. cmd.Env = append(os.Environ(), "BE_CRASHER=1")
  773. err := cmd.Run()
  774. if e, ok := err.(*exec.ExitError); ok && !e.Success() {
  775. return
  776. }
  777. t.Error("Server started with a bad TLS config, was expecting exit status 1")
  778. // cleanup
  779. os.Truncate("../../tests/testlog", 0)
  780. os.Remove("configJsonD.json")
  781. os.Remove("./pidfile.pid")
  782. }
  783. // Test config reload with a bad TLS config
  784. // It should ignore the config reload, keep running with old settings
  785. func TestBadTLSReload(t *testing.T) {
  786. mainlog, _ = log.GetLogger("../../tests/testlog")
  787. // start with a good vert
  788. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  789. // start the server by emulating the serve command
  790. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  791. conf := &CmdConfig{} // blank one
  792. conf.load([]byte(configJsonD)) // load configJsonD
  793. cmd := &cobra.Command{}
  794. configPath = "configJsonD.json"
  795. var serveWG sync.WaitGroup
  796. serveWG.Add(1)
  797. go func() {
  798. serve(cmd, []string{})
  799. serveWG.Done()
  800. }()
  801. time.Sleep(testPauseDuration)
  802. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  803. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  804. } else {
  805. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  806. expect := "250 mail.test.com Hello"
  807. if strings.Index(result, expect) != 0 {
  808. t.Error("Expected", expect, "but got", result)
  809. }
  810. }
  811. }
  812. // write some trash data
  813. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.cert.pem", []byte("trash data"), 0664)
  814. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.key.pem", []byte("trash data"), 0664)
  815. newConf := conf // copy the cmdConfg
  816. if jsonbytes, err := json.Marshal(newConf); err == nil {
  817. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  818. } else {
  819. t.Error(err)
  820. }
  821. // send a sighup signal to the server to reload config
  822. sigHup()
  823. time.Sleep(testPauseDuration) // pause for config to reload
  824. // we should still be able to to talk to it
  825. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  826. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  827. } else {
  828. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  829. expect := "250 mail.test.com Hello"
  830. if strings.Index(result, expect) != 0 {
  831. t.Error("Expected", expect, "but got", result)
  832. }
  833. }
  834. }
  835. sigKill()
  836. serveWG.Wait()
  837. // did config reload fail as expected?
  838. fd, _ := os.Open("../../tests/testlog")
  839. if read, err := ioutil.ReadAll(fd); err == nil {
  840. logOutput := string(read)
  841. //fmt.Println(logOutput)
  842. if i := strings.Index(logOutput, "cannot use TLS config for"); i < 0 {
  843. t.Error("[127.0.0.1:2552] did not reject our tls config as expected")
  844. }
  845. }
  846. // cleanup
  847. os.Truncate("../../tests/testlog", 0)
  848. os.Remove("configJsonD.json")
  849. os.Remove("./pidfile.pid")
  850. }
  851. // Test for when the server config Timeout value changes
  852. // Start with configJsonD.json
  853. func TestSetTimeoutEvent(t *testing.T) {
  854. mainlog, _ = log.GetLogger("../../tests/testlog")
  855. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  856. // start the server by emulating the serve command
  857. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  858. conf := &CmdConfig{} // blank one
  859. conf.load([]byte(configJsonD)) // load configJsonD
  860. cmd := &cobra.Command{}
  861. configPath = "configJsonD.json"
  862. var serveWG sync.WaitGroup
  863. serveWG.Add(1)
  864. go func() {
  865. serve(cmd, []string{})
  866. serveWG.Done()
  867. }()
  868. time.Sleep(testPauseDuration)
  869. // set the timeout to 1 second
  870. newConf := conf // copy the cmdConfg
  871. newConf.Servers[0].Timeout = 1
  872. if jsonbytes, err := json.Marshal(newConf); err == nil {
  873. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  874. } else {
  875. t.Error(err)
  876. }
  877. // send a sighup signal to the server to reload config
  878. sigHup()
  879. time.Sleep(testPauseDuration) // config reload
  880. var waitTimeout sync.WaitGroup
  881. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  882. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  883. } else {
  884. waitTimeout.Add(1)
  885. go func() {
  886. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  887. expect := "250 mail.test.com Hello"
  888. if strings.Index(result, expect) != 0 {
  889. t.Error("Expected", expect, "but got", result)
  890. } else {
  891. b := make([]byte, 1024)
  892. conn.Read(b)
  893. }
  894. }
  895. waitTimeout.Done()
  896. }()
  897. }
  898. // wait for timeout
  899. waitTimeout.Wait()
  900. // so the connection we have opened should timeout by now
  901. // send kill signal and wait for exit
  902. sigKill()
  903. serveWG.Wait()
  904. // did backend started as expected?
  905. fd, _ := os.Open("../../tests/testlog")
  906. if read, err := ioutil.ReadAll(fd); err == nil {
  907. logOutput := string(read)
  908. fmt.Println(logOutput)
  909. if i := strings.Index(logOutput, "i/o timeout"); i < 0 {
  910. t.Error("Connection to 127.0.0.1:2552 didn't timeout as expected")
  911. }
  912. }
  913. // cleanup
  914. os.Truncate("../../tests/testlog", 0)
  915. os.Remove("configJsonD.json")
  916. os.Remove("./pidfile.pid")
  917. }
  918. // Test debug level config change
  919. // Start in log_level = debug
  920. // Load config & start server
  921. func TestDebugLevelChange(t *testing.T) {
  922. //mainlog, _ = log.GetLogger("../../tests/testlog")
  923. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  924. // start the server by emulating the serve command
  925. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  926. conf := &CmdConfig{} // blank one
  927. conf.load([]byte(configJsonD)) // load configJsonD
  928. conf.LogLevel = "debug"
  929. cmd := &cobra.Command{}
  930. configPath = "configJsonD.json"
  931. var serveWG sync.WaitGroup
  932. serveWG.Add(1)
  933. go func() {
  934. serve(cmd, []string{})
  935. serveWG.Done()
  936. }()
  937. time.Sleep(testPauseDuration)
  938. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  939. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  940. } else {
  941. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  942. expect := "250 mail.test.com Hello"
  943. if strings.Index(result, expect) != 0 {
  944. t.Error("Expected", expect, "but got", result)
  945. }
  946. }
  947. conn.Close()
  948. }
  949. // set the log_level to info
  950. newConf := conf // copy the cmdConfg
  951. newConf.LogLevel = "info"
  952. if jsonbytes, err := json.Marshal(newConf); err == nil {
  953. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  954. } else {
  955. t.Error(err)
  956. }
  957. // send a sighup signal to the server to reload config
  958. sigHup()
  959. time.Sleep(testPauseDuration) // log to change
  960. // connect again, this time we should see info
  961. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  962. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  963. } else {
  964. if result, err := test.Command(conn, buffin, "NOOP"); err == nil {
  965. expect := "200 2.0.0 OK"
  966. if strings.Index(result, expect) != 0 {
  967. t.Error("Expected", expect, "but got", result)
  968. }
  969. }
  970. conn.Close()
  971. }
  972. // send kill signal and wait for exit
  973. sigKill()
  974. serveWG.Wait()
  975. // did backend started as expected?
  976. fd, _ := os.Open("../../tests/testlog")
  977. if read, err := ioutil.ReadAll(fd); err == nil {
  978. logOutput := string(read)
  979. //fmt.Println(logOutput)
  980. if i := strings.Index(logOutput, "log level changed to [info]"); i < 0 {
  981. t.Error("Log level did not change to [info]")
  982. }
  983. // This should not be there:
  984. if i := strings.Index(logOutput, "Client sent: NOOP"); i != -1 {
  985. t.Error("Log level did not change to [info], we are still seeing debug messages")
  986. }
  987. }
  988. // cleanup
  989. os.Truncate("../../tests/testlog", 0)
  990. os.Remove("configJsonD.json")
  991. os.Remove("./pidfile.pid")
  992. }