1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package testutils2021import (22 "bufio"23 "context"24 "crypto/sha1"25 "encoding/hex"26 "io"27 "strconv"28 "strings"29 "testing"3031 "github.com/emersion/go-message/textproto"32 "github.com/emersion/go-smtp"33 "github.com/foxcpp/maddy/framework/buffer"34 "github.com/foxcpp/maddy/framework/module"35)3637// Empirically observed "around average" values.38const (39 MessageBodySize = 100 * 102440 ExtraMessageHeaderFields = 1041 ExtraMessageHeaderFieldSize = 5042)4344const testHeaderString = "Content-Type: multipart/mixed; boundary=message-boundary\r\n" +45 "Date: Sat, 19 Jun 2016 12:00:00 +0900\r\n" +46 "From: Mitsuha Miyamizu <mitsuha.miyamizu@example.org>\r\n" +47 "Reply-To: Mitsuha Miyamizu <mitsuha.miyamizu+replyto@example.org>\r\n" +48 "Message-Id: 42@example.org\r\n" +49 "MIME-Version: 1.0\r\n" +50 "Content-Transfer-Encoding: 8but\r\n" +51 "Subject: Your Name.\r\n" +52 "To: Taki Tachibana <taki.tachibana@example.org>\r\n" +53 "\r\n"5455const testAltHeaderString = "Content-Type: multipart/alternative; boundary=b2\r\n" +56 "\r\n"5758const testTextHeaderString = "Content-Disposition: inline\r\n" +59 "Content-Type: text/plain\r\n" +60 "\r\n"6162const testTextBodyString = "What's your name?"6364const testTextString = testTextHeaderString + testTextBodyString6566const testHTMLHeaderString = "Content-Disposition: inline\r\n" +67 "Content-Type: text/html\r\n" +68 "\r\n"6970const testHTMLBodyString = "<div>What's <i>your</i> name?</div>"7172const testHTMLString = testHTMLHeaderString + testHTMLBodyString7374const testAttachmentHeaderString = "Content-Disposition: attachment; filename=note.txt\r\n" +75 "Content-Type: text/plain\r\n" +76 "\r\n"7778const testAttachmentBodyString = "My name is Mitsuha."7980const testAttachmentString = testAttachmentHeaderString + testAttachmentBodyString8182const testBodyString = "--message-boundary\r\n" +83 testAltHeaderString +84 "\r\n--b2\r\n" +85 testTextString +86 "\r\n--b2\r\n" +87 testHTMLString +88 "\r\n--b2--\r\n" +89 "\r\n--message-boundary\r\n" +90 testAttachmentString +91 "\r\n--message-boundary--\r\n"9293var testMailString = testHeaderString + testBodyString + strings.Repeat("A", MessageBodySize)9495func RandomMsg(b *testing.B) (module.MsgMetadata, textproto.Header, buffer.Buffer) {96 IDRaw := sha1.Sum([]byte(b.Name()))97 encodedID := hex.EncodeToString(IDRaw[:])9899 body := bufio.NewReader(strings.NewReader(testMailString))100 hdr, _ := textproto.ReadHeader(body)101 for i := 0; i < ExtraMessageHeaderFields; i++ {102 hdr.Add("AAAAAAAAAAAA-"+strconv.Itoa(i), strings.Repeat("A", ExtraMessageHeaderFieldSize))103 }104 bodyBlob, _ := io.ReadAll(body)105106 return module.MsgMetadata{107 DontTraceSender: true,108 ID: encodedID,109 }, hdr, buffer.MemoryBuffer{Slice: bodyBlob}110}111112func BenchDelivery(b *testing.B, target module.DeliveryTarget, sender string, recipientTemplates []string) {113 meta, header, body := RandomMsg(b)114115 benchCtx := context.Background()116117 b.ReportAllocs()118 b.ResetTimer()119 for i := 0; i < b.N; i++ {120 delivery, err := target.Start(benchCtx, &meta, sender)121 if err != nil {122 b.Fatal(err)123 }124125 for i, rcptTemplate := range recipientTemplates {126 rcpt := strings.Replace(rcptTemplate, "X", strconv.Itoa(i), -1)127128 if err := delivery.AddRcpt(benchCtx, rcpt, smtp.RcptOptions{}); err != nil {129 b.Fatal(err)130 }131 }132133 if err := delivery.Body(benchCtx, header, body); err != nil {134 b.Fatal(err)135 }136137 if err := delivery.Commit(benchCtx); err != nil {138 b.Fatal(err)139 }140 }141}