store_sql_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. /*
  55. total := 0
  56. for _, chunk := range storeMemory.chunks {
  57. total += len(chunk.data)
  58. }
  59. fmt.Println("compressed", total, "saved:", written-int64(total))
  60. */
  61. /*
  62. part 5 (gif)
  63. 5a94c939c7101636fc19f266f701968b
  64. 45c5d2a84119b3a21b0306a9524b361a
  65. 74eb56d4dd331e3d8c76a373556d6bcb
  66. hash 5a94c939c7101636fc19f266f701968b h 45c5d2a84119b3a21b0306a9524b361a i 0
  67. hash 45c5d2a84119b3a21b0306a9524b361a h 5a94c939c7101636fc19f266f701968b i 1
  68. hash 74eb56d4dd331e3d8c76a373556d6bcb h 74eb56d4dd331e3d8c76a373556d6bcb i 0
  69. */
  70. email, err := storeSql.GetEmail(e.MessageID)
  71. if err != nil {
  72. t.Error("email not found")
  73. return
  74. }
  75. // check email
  76. if email.transport != smtp.TransportType8bit {
  77. t.Error("email.transport not ", smtp.TransportType8bit.String())
  78. }
  79. if email.protocol != mail.ProtocolESMTPS {
  80. t.Error("email.protocol not ", mail.ProtocolESMTPS)
  81. }
  82. // this should read all parts
  83. r, err := NewChunkedReader(storeSql, email, 0)
  84. if w, err := io.Copy(&out, r); err != nil {
  85. t.Error(err)
  86. } else if w != email.size {
  87. t.Error("email.size != number of bytes copied from reader", w, email.size)
  88. } else if !strings.Contains(out.String(), "R0lGODlhEAA") {
  89. t.Error("The email didn't decode properly, expecting R0lGODlhEAA")
  90. }
  91. out.Reset()
  92. return
  93. // test the seek feature
  94. r, err = NewChunkedReader(storeSql, email, 0)
  95. if err != nil {
  96. t.Error(err)
  97. t.FailNow()
  98. }
  99. // we start from 1 because if the start from 0, all the parts will be read
  100. for i := 1; i < len(email.partsInfo.Parts); i++ {
  101. fmt.Println("seeking to", i)
  102. err = r.SeekPart(i)
  103. if err != nil {
  104. t.Error(err)
  105. }
  106. w, err := io.Copy(&out, r)
  107. if err != nil {
  108. t.Error(err)
  109. }
  110. if w != int64(email.partsInfo.Parts[i-1].Size) {
  111. t.Error(i, "incorrect size, expecting", email.partsInfo.Parts[i-1].Size, "but read:", w)
  112. }
  113. out.Reset()
  114. }
  115. r, err = NewChunkedReader(storeSql, email, 0)
  116. if err != nil {
  117. t.Error(err)
  118. }
  119. part := email.partsInfo.Parts[0]
  120. encoding := transfer.QuotedPrintable
  121. if strings.Contains(part.TransferEncoding, "base") {
  122. encoding = transfer.Base64
  123. }
  124. dr, err := transfer.NewDecoder(r, encoding, part.Charset)
  125. _ = dr
  126. if err != nil {
  127. t.Error(err)
  128. t.FailNow()
  129. }
  130. //var decoded bytes.Buffer
  131. //io.Copy(&decoded, dr)
  132. io.Copy(os.Stdout, dr)
  133. }
  134. }