1package store
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7 "time"
8
9 "github.com/mjl-/bstore"
10
11 "github.com/mjl-/mox/message"
12 "github.com/mjl-/mox/mlog"
13 "github.com/mjl-/mox/mox-"
14)
15
16func TestReparse(t *testing.T) {
17 log := mlog.New("store", nil)
18 os.RemoveAll("../testdata/store/data")
19 mox.ConfigStaticPath = filepath.FromSlash("../testdata/store/mox.conf")
20 mox.MustLoadConfig(true, false)
21 err := Init(ctxbg)
22 tcheck(t, err, "init")
23 defer func() {
24 err := Close()
25 tcheck(t, err, "close")
26 }()
27 defer Switchboard()()
28
29 orig := reparseMessageBatchSize
30 reparseMessageBatchSize = 2
31 defer func() {
32 reparseMessageBatchSize = orig
33 }()
34
35 acc, err := OpenAccount(log, "mjl", false)
36 tcheck(t, err, "open account")
37
38 // Prepare message to add later.
39 msgFile, err := CreateMessageTemp(log, "account-test")
40 tcheck(t, err, "create temp message file")
41 defer CloseRemoveTempFile(log, msgFile, "temp message file")
42 msgWriter := message.NewWriter(msgFile)
43 _, err = msgWriter.Write([]byte(" message"))
44 tcheck(t, err, "write message")
45
46 msgPrefix := []byte("From: <mjl@mox.example\r\nTo: <mjl@mox.example>\r\nCc: <mjl@mox.example>Subject: test\r\nMessage-Id: <m01@mox.example>\r\n\r\n")
47 m := Message{
48 Received: time.Now(),
49 Size: int64(len(msgPrefix)) + msgWriter.Size,
50 MsgPrefix: msgPrefix,
51 }
52
53 // Add messages.
54 acc.WithRLock(func() {
55 conf, _ := acc.Conf()
56 for range 10 {
57 nm := m
58 err := acc.DeliverDestination(log, conf.Destinations["mjl"], &nm, msgFile)
59 tcheck(t, err, "deliver")
60 }
61 })
62
63 // Reparse explicitly.
64 total, err := acc.ReparseMessages(ctxbg, log)
65 tcheck(t, err, "reparsing messages")
66 tcompare(t, total, 10)
67
68 // Ensure a next reopen will reparse messages in the background.
69 _, err = bstore.QueryDB[Upgrade](ctxbg, acc.DB).UpdateNonzero(Upgrade{MessageParseVersion: MessageParseVersionLatest + 1})
70 tcheck(t, err, "change")
71
72 // Close account, and wait until really closed.
73 err = acc.Close()
74 tcheck(t, err, "closing account")
75 acc.WaitClosed()
76
77 // Reopen account, should trigger reparse. We immediately Close again, account DB
78 // should be kept open.
79 acc, err = OpenAccount(log, "mjl", false)
80 tcheck(t, err, "open account")
81 err = acc.Close()
82 tcheck(t, err, "closing account")
83 acc.WaitClosed()
84
85 // Check that the reparse is finished.
86 acc, err = OpenAccount(log, "mjl", false)
87 tcheck(t, err, "open account")
88 for range 10 {
89 up, err := bstore.QueryDB[Upgrade](ctxbg, acc.DB).Get()
90 tcheck(t, err, "change")
91 if up.MessageParseVersion == MessageParseVersionLatest {
92 break
93 }
94 time.Sleep(time.Second / 10)
95 }
96 err = acc.Close()
97 tcheck(t, err, "closing account")
98 acc.WaitClosed()
99}
100