store_sql_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package chunk
  2. import (
  3. "bytes"
  4. "flag"
  5. "fmt"
  6. "github.com/flashmob/go-guerrilla/mail"
  7. "github.com/flashmob/go-guerrilla/mail/smtp"
  8. "io"
  9. "os"
  10. "strings"
  11. "testing"
  12. "github.com/flashmob/go-guerrilla/backends"
  13. "github.com/flashmob/go-guerrilla/chunk/transfer"
  14. _ "github.com/go-sql-driver/mysql" // activate the mysql driver
  15. )
  16. // This test requires that you pass the -sql-dsn flag,
  17. // eg: go test -run ^TestSQLStore$ -sql-dsn 'user:pass@tcp(127.0.0.1:3306)/dbname?readTimeout=10s&writeTimeout=10s'
  18. var (
  19. mailTableFlag = flag.String("mail-table", "in_emails", "Table to use for testing the SQL backend")
  20. chunkTableFlag = flag.String("mail-chunk-table", "in_emails_chunks", "Table to use for testing the chunking SQL backend")
  21. sqlDSNFlag = flag.String("sql-dsn", "", "DSN to use for testing the SQL backend")
  22. sqlDriverFlag = flag.String("sql-driver", "mysql", "Driver to use for testing the SQL backend")
  23. )
  24. func TestSQLStore(t *testing.T) {
  25. if *sqlDSNFlag == "" {
  26. t.Skip("requires -sql-dsn to run")
  27. }
  28. cfg := &backends.ConfigGroup{
  29. "chunk_size": 150,
  30. "storage_engine": "sql",
  31. "compress_level": 9,
  32. "sql_driver": *sqlDriverFlag,
  33. "sql_dsn": *sqlDSNFlag,
  34. "email_table": *mailTableFlag,
  35. "email_table_chunks": *chunkTableFlag,
  36. }
  37. store, chunksaver, mimeanalyzer, stream, e, err := initTestStream(false, cfg)
  38. if err != nil {
  39. t.Error(err)
  40. return
  41. }
  42. storeSql := store.(*StoreSQL)
  43. defer func() {
  44. storeSql.zap() // purge everything from db before exiting the test
  45. }()
  46. var out bytes.Buffer
  47. buf := make([]byte, 128)
  48. if written, err := io.CopyBuffer(stream, bytes.NewBuffer([]byte(email)), buf); err != nil {
  49. t.Error(err)
  50. } else {
  51. _ = mimeanalyzer.Close()
  52. _ = chunksaver.Close()
  53. fmt.Println("written:", written)
  54. email, err := storeSql.GetMessage(e.MessageID)
  55. if err != nil {
  56. t.Error("email not found")
  57. return
  58. }
  59. // check email
  60. if email.transport != smtp.TransportType8bit {
  61. t.Error("email.transport not ", smtp.TransportType8bit.String())
  62. }
  63. if email.protocol != mail.ProtocolESMTPS {
  64. t.Error("email.protocol not ", mail.ProtocolESMTPS)
  65. }
  66. // this should read all parts
  67. r, err := NewChunkedReader(storeSql, email, 0)
  68. if w, err := io.Copy(&out, r); err != nil {
  69. t.Error(err)
  70. } else if w != email.size {
  71. t.Error("email.size != number of bytes copied from reader", w, email.size)
  72. } else if !strings.Contains(out.String(), "R0lGODlhEAA") {
  73. t.Error("The email didn't decode properly, expecting R0lGODlhEAA")
  74. }
  75. out.Reset()
  76. return
  77. // test the seek feature
  78. r, err = NewChunkedReader(storeSql, email, 0)
  79. if err != nil {
  80. t.Error(err)
  81. t.FailNow()
  82. }
  83. // we start from 1 because if the start from 0, all the parts will be read
  84. for i := 1; i < len(email.partsInfo.Parts); i++ {
  85. fmt.Println("seeking to", i)
  86. err = r.SeekPart(i)
  87. if err != nil {
  88. t.Error(err)
  89. }
  90. w, err := io.Copy(&out, r)
  91. if err != nil {
  92. t.Error(err)
  93. }
  94. if w != int64(email.partsInfo.Parts[i-1].Size) {
  95. t.Error(i, "incorrect size, expecting", email.partsInfo.Parts[i-1].Size, "but read:", w)
  96. }
  97. out.Reset()
  98. }
  99. r, err = NewChunkedReader(storeSql, email, 0)
  100. if err != nil {
  101. t.Error(err)
  102. }
  103. part := email.partsInfo.Parts[0]
  104. encoding := transfer.QuotedPrintable
  105. if strings.Contains(part.TransferEncoding, "base") {
  106. encoding = transfer.Base64
  107. }
  108. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  109. _ = dr
  110. if err != nil {
  111. t.Error(err)
  112. t.FailNow()
  113. }
  114. //var decoded bytes.Buffer
  115. //io.Copy(&decoded, dr)
  116. io.Copy(os.Stdout, dr)
  117. }
  118. }