// Copyright (c) 2020 Proton Technologies AG // // This file is part of ProtonMail Bridge. // // ProtonMail Bridge is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ProtonMail Bridge is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with ProtonMail Bridge. If not, see . package store import ( "encoding/json" "fmt" "github.com/ProtonMail/proton-bridge/pkg/pmapi" "github.com/stretchr/testify/assert" bolt "go.etcd.io/bbolt" ) // TestSync triggers a sync of the store. func (store *Store) TestSync() { store.lock.Lock() defer store.lock.Unlock() // Sync can happen any time. Sync assigns sequence numbers and UIDs // in the order of fetching from the server. We expect in the test // that sequence numbers and UIDs are assigned in the same order as // written in scenario setup. With more than one sync that cannot // be guaranteed so once test calls this function, first it has to // delete previous any already synced sequence numbers and UIDs. _ = store.truncateMailboxesBucket() store.triggerSync() } // TestPollNow triggers a loop of the event loop. func (store *Store) TestPollNow() { store.eventLoop.pollNow() } // TestIsSyncRunning returns whether the sync is currently ongoing. func (store *Store) TestIsSyncRunning() bool { return store.isSyncRunning } // TestGetEventLoop returns the store's event loop. func (store *Store) TestGetEventLoop() *eventLoop { //nolint[golint] return store.eventLoop } // TestGetLastEvent returns last event processed by the store's event loop. func (store *Store) TestGetLastEvent() *pmapi.Event { return store.eventLoop.currentEvent } // TestGetStoreFilePath returns the filepath of the store's database file. func (store *Store) TestGetStoreFilePath() string { return store.filePath } // TestDumpDB will dump store database content. func (store *Store) TestDumpDB(tb assert.TestingT) { if store == nil || store.db == nil { fmt.Printf(">>>>>>>> NIL STORE / DB <<<<<\n\n") assert.Fail(tb, "store or database is nil") return } dumpCounts := true fmt.Printf(">>>>>>>> DUMP %s <<<<<\n\n", store.db.Path()) txMails := txDumpMailsFactory(tb) txDump := func(tx *bolt.Tx) error { if dumpCounts { if err := txDumpCounts(tx); err != nil { return err } } if err := txMails(tx); err != nil { return err } return nil } assert.NoError(tb, store.db.View(txDump)) } func txDumpMailsFactory(tb assert.TestingT) func(tx *bolt.Tx) error { return func(tx *bolt.Tx) error { mailboxes := tx.Bucket(mailboxesBucket) metadata := tx.Bucket(metadataBucket) err := mailboxes.ForEach(func(mboxName, mboxData []byte) error { fmt.Println("mbox:", string(mboxName)) b := mailboxes.Bucket(mboxName).Bucket(imapIDsBucket) c := b.Cursor() i := 0 for imapID, apiID := c.First(); imapID != nil; imapID, apiID = c.Next() { i++ fmt.Println(" ", i, "imap", btoi(imapID), "api", string(apiID)) data := metadata.Get(apiID) if !assert.NotNil(tb, data) { continue } if !assert.NoError(tb, txMailMeta(data, i)) { continue } } fmt.Println("total:", i) return nil }) return err } } func txDumpCounts(tx *bolt.Tx) error { counts := tx.Bucket(countsBucket) err := counts.ForEach(func(labelID, countsB []byte) error { defer fmt.Println() fmt.Printf("counts id: %q ", string(labelID)) counts := &mailboxCounts{} if err := json.Unmarshal(countsB, counts); err != nil { fmt.Printf(" Error %v", err) return nil } fmt.Printf(" total :%d unread %d", counts.TotalOnAPI, counts.UnreadOnAPI) return nil }) return err } func txMailMeta(data []byte, i int) error { fullMetaDump := false msg := &pmapi.Message{} if err := json.Unmarshal(data, msg); err != nil { return err } if msg.Body != "" { fmt.Printf(" %d body %s\n\n", i, msg.Body) panic("NONZERO BODY") } if i >= 10 { return nil } if fullMetaDump { fmt.Printf(" %d meta %s\n\n", i, string(data)) } else { fmt.Println( " Subj", msg.Subject, "\n From", msg.Sender, "\n Time", msg.Time, "\n Labels", msg.LabelIDs, "\n Unread", msg.Unread, ) } return nil }