github.com/gophish/gophish@v0.12.2-0.20230915144530-8e7929441393/models/campaign_test.go (about) 1 package models 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 check "gopkg.in/check.v1" 9 ) 10 11 func (s *ModelsSuite) TestGenerateSendDate(c *check.C) { 12 campaign := s.createCampaignDependencies(c) 13 // Test that if no launch date is provided, the campaign's creation date 14 // is used. 15 err := PostCampaign(&campaign, campaign.UserId) 16 c.Assert(err, check.Equals, nil) 17 c.Assert(campaign.LaunchDate, check.Equals, campaign.CreatedDate) 18 19 // For comparing the dates, we need to fetch the campaign again. This is 20 // to solve an issue where the campaign object right now has time down to 21 // the microsecond, while in MySQL it's rounded down to the second. 22 campaign, _ = GetCampaign(campaign.Id, campaign.UserId) 23 24 ms, err := GetMailLogsByCampaign(campaign.Id) 25 c.Assert(err, check.Equals, nil) 26 for _, m := range ms { 27 c.Assert(m.SendDate, check.Equals, campaign.CreatedDate) 28 } 29 30 // Test that if no send date is provided, all the emails are sent at the 31 // campaign's launch date 32 campaign = s.createCampaignDependencies(c) 33 campaign.LaunchDate = time.Now().UTC() 34 err = PostCampaign(&campaign, campaign.UserId) 35 c.Assert(err, check.Equals, nil) 36 37 campaign, _ = GetCampaign(campaign.Id, campaign.UserId) 38 39 ms, err = GetMailLogsByCampaign(campaign.Id) 40 c.Assert(err, check.Equals, nil) 41 for _, m := range ms { 42 c.Assert(m.SendDate, check.Equals, campaign.LaunchDate) 43 } 44 45 // Finally, test that if a send date is provided, the emails are staggered 46 // correctly. 47 campaign = s.createCampaignDependencies(c) 48 campaign.LaunchDate = time.Now().UTC() 49 campaign.SendByDate = campaign.LaunchDate.Add(2 * time.Minute) 50 err = PostCampaign(&campaign, campaign.UserId) 51 c.Assert(err, check.Equals, nil) 52 53 campaign, _ = GetCampaign(campaign.Id, campaign.UserId) 54 55 ms, err = GetMailLogsByCampaign(campaign.Id) 56 c.Assert(err, check.Equals, nil) 57 sendingOffset := 2 / float64(len(ms)) 58 for i, m := range ms { 59 expectedOffset := int(sendingOffset * float64(i)) 60 expectedDate := campaign.LaunchDate.Add(time.Duration(expectedOffset) * time.Minute) 61 c.Assert(m.SendDate, check.Equals, expectedDate) 62 } 63 } 64 65 func (s *ModelsSuite) TestCampaignDateValidation(c *check.C) { 66 campaign := s.createCampaignDependencies(c) 67 // If both are zero, then the campaign should start immediately with no 68 // send by date 69 err := campaign.Validate() 70 c.Assert(err, check.Equals, nil) 71 72 // If the launch date is specified, then the send date is optional 73 campaign = s.createCampaignDependencies(c) 74 campaign.LaunchDate = time.Now().UTC() 75 err = campaign.Validate() 76 c.Assert(err, check.Equals, nil) 77 78 // If the send date is greater than the launch date, then there's no 79 //problem 80 campaign = s.createCampaignDependencies(c) 81 campaign.LaunchDate = time.Now().UTC() 82 campaign.SendByDate = campaign.LaunchDate.Add(1 * time.Minute) 83 err = campaign.Validate() 84 c.Assert(err, check.Equals, nil) 85 86 // If the send date is less than the launch date, then there's an issue 87 campaign = s.createCampaignDependencies(c) 88 campaign.LaunchDate = time.Now().UTC() 89 campaign.SendByDate = campaign.LaunchDate.Add(-1 * time.Minute) 90 err = campaign.Validate() 91 c.Assert(err, check.Equals, ErrInvalidSendByDate) 92 } 93 94 func (s *ModelsSuite) TestLaunchCampaignMaillogStatus(c *check.C) { 95 // For the first test, ensure that campaigns created with the zero date 96 // (and therefore are set to launch immediately) have maillogs that are 97 // locked to prevent race conditions. 98 campaign := s.createCampaign(c) 99 ms, err := GetMailLogsByCampaign(campaign.Id) 100 c.Assert(err, check.Equals, nil) 101 102 for _, m := range ms { 103 c.Assert(m.Processing, check.Equals, true) 104 } 105 106 // Next, verify that campaigns scheduled in the future do not lock the 107 // maillogs so that they can be picked up by the background worker. 108 campaign = s.createCampaignDependencies(c) 109 campaign.Name = "New Campaign" 110 campaign.LaunchDate = time.Now().Add(1 * time.Hour) 111 c.Assert(PostCampaign(&campaign, campaign.UserId), check.Equals, nil) 112 ms, err = GetMailLogsByCampaign(campaign.Id) 113 c.Assert(err, check.Equals, nil) 114 115 for _, m := range ms { 116 c.Assert(m.Processing, check.Equals, false) 117 } 118 } 119 120 func (s *ModelsSuite) TestDeleteCampaignAlsoDeletesMailLogs(c *check.C) { 121 campaign := s.createCampaign(c) 122 ms, err := GetMailLogsByCampaign(campaign.Id) 123 c.Assert(err, check.Equals, nil) 124 c.Assert(len(ms), check.Equals, len(campaign.Results)) 125 126 err = DeleteCampaign(campaign.Id) 127 c.Assert(err, check.Equals, nil) 128 129 ms, err = GetMailLogsByCampaign(campaign.Id) 130 c.Assert(err, check.Equals, nil) 131 c.Assert(len(ms), check.Equals, 0) 132 } 133 134 func (s *ModelsSuite) TestCompleteCampaignAlsoDeletesMailLogs(c *check.C) { 135 campaign := s.createCampaign(c) 136 ms, err := GetMailLogsByCampaign(campaign.Id) 137 c.Assert(err, check.Equals, nil) 138 c.Assert(len(ms), check.Equals, len(campaign.Results)) 139 140 err = CompleteCampaign(campaign.Id, campaign.UserId) 141 c.Assert(err, check.Equals, nil) 142 143 ms, err = GetMailLogsByCampaign(campaign.Id) 144 c.Assert(err, check.Equals, nil) 145 c.Assert(len(ms), check.Equals, 0) 146 } 147 148 func (s *ModelsSuite) TestCampaignGetResults(c *check.C) { 149 campaign := s.createCampaign(c) 150 got, err := GetCampaign(campaign.Id, campaign.UserId) 151 c.Assert(err, check.Equals, nil) 152 c.Assert(len(campaign.Results), check.Equals, len(got.Results)) 153 } 154 155 func setupCampaignDependencies(b *testing.B, size int) { 156 group := Group{Name: "Test Group"} 157 // Create a large group of 5000 members 158 for i := 0; i < size; i++ { 159 group.Targets = append(group.Targets, Target{BaseRecipient: BaseRecipient{Email: fmt.Sprintf("test%d@example.com", i), FirstName: "User", LastName: fmt.Sprintf("%d", i)}}) 160 } 161 group.UserId = 1 162 err := PostGroup(&group) 163 if err != nil { 164 b.Fatalf("error posting group: %v", err) 165 } 166 167 // Add a template 168 template := Template{Name: "Test Template"} 169 template.Subject = "{{.RId}} - Subject" 170 template.Text = "{{.RId}} - Text" 171 template.HTML = "{{.RId}} - HTML" 172 template.UserId = 1 173 err = PostTemplate(&template) 174 if err != nil { 175 b.Fatalf("error posting template: %v", err) 176 } 177 178 // Add a landing page 179 p := Page{Name: "Test Page"} 180 p.HTML = "<html>Test</html>" 181 p.UserId = 1 182 err = PostPage(&p) 183 if err != nil { 184 b.Fatalf("error posting page: %v", err) 185 } 186 187 // Add a sending profile 188 smtp := SMTP{Name: "Test Page"} 189 smtp.UserId = 1 190 smtp.Host = "example.com" 191 smtp.FromAddress = "test@test.com" 192 err = PostSMTP(&smtp) 193 if err != nil { 194 b.Fatalf("error posting smtp: %v", err) 195 } 196 } 197 198 // setupCampaign sets up the campaign dependencies as well as posting the 199 // actual campaign 200 func setupCampaign(b *testing.B, size int) Campaign { 201 setupCampaignDependencies(b, size) 202 campaign := Campaign{Name: "Test campaign"} 203 campaign.UserId = 1 204 campaign.Template = Template{Name: "Test Template"} 205 campaign.Page = Page{Name: "Test Page"} 206 campaign.SMTP = SMTP{Name: "Test Page"} 207 campaign.Groups = []Group{Group{Name: "Test Group"}} 208 PostCampaign(&campaign, 1) 209 return campaign 210 } 211 212 func BenchmarkCampaign100(b *testing.B) { 213 setupBenchmark(b) 214 setupCampaignDependencies(b, 100) 215 b.ResetTimer() 216 for i := 0; i < b.N; i++ { 217 campaign := Campaign{Name: "Test campaign"} 218 campaign.UserId = 1 219 campaign.Template = Template{Name: "Test Template"} 220 campaign.Page = Page{Name: "Test Page"} 221 campaign.SMTP = SMTP{Name: "Test Page"} 222 campaign.Groups = []Group{Group{Name: "Test Group"}} 223 224 b.StartTimer() 225 err := PostCampaign(&campaign, 1) 226 if err != nil { 227 b.Fatalf("error posting campaign: %v", err) 228 } 229 b.StopTimer() 230 db.Delete(Result{}) 231 db.Delete(MailLog{}) 232 db.Delete(Campaign{}) 233 } 234 tearDownBenchmark(b) 235 } 236 237 func BenchmarkCampaign1000(b *testing.B) { 238 setupBenchmark(b) 239 setupCampaignDependencies(b, 1000) 240 b.ResetTimer() 241 for i := 0; i < b.N; i++ { 242 campaign := Campaign{Name: "Test campaign"} 243 campaign.UserId = 1 244 campaign.Template = Template{Name: "Test Template"} 245 campaign.Page = Page{Name: "Test Page"} 246 campaign.SMTP = SMTP{Name: "Test Page"} 247 campaign.Groups = []Group{Group{Name: "Test Group"}} 248 249 b.StartTimer() 250 err := PostCampaign(&campaign, 1) 251 if err != nil { 252 b.Fatalf("error posting campaign: %v", err) 253 } 254 b.StopTimer() 255 db.Delete(Result{}) 256 db.Delete(MailLog{}) 257 db.Delete(Campaign{}) 258 } 259 tearDownBenchmark(b) 260 } 261 262 func BenchmarkCampaign10000(b *testing.B) { 263 setupBenchmark(b) 264 setupCampaignDependencies(b, 10000) 265 b.ResetTimer() 266 for i := 0; i < b.N; i++ { 267 campaign := Campaign{Name: "Test campaign"} 268 campaign.UserId = 1 269 campaign.Template = Template{Name: "Test Template"} 270 campaign.Page = Page{Name: "Test Page"} 271 campaign.SMTP = SMTP{Name: "Test Page"} 272 campaign.Groups = []Group{Group{Name: "Test Group"}} 273 274 b.StartTimer() 275 err := PostCampaign(&campaign, 1) 276 if err != nil { 277 b.Fatalf("error posting campaign: %v", err) 278 } 279 b.StopTimer() 280 db.Delete(Result{}) 281 db.Delete(MailLog{}) 282 db.Delete(Campaign{}) 283 } 284 tearDownBenchmark(b) 285 } 286 287 func BenchmarkGetCampaign100(b *testing.B) { 288 setupBenchmark(b) 289 campaign := setupCampaign(b, 100) 290 b.ResetTimer() 291 for i := 0; i < b.N; i++ { 292 _, err := GetCampaign(campaign.Id, campaign.UserId) 293 if err != nil { 294 b.Fatalf("error getting campaign: %v", err) 295 } 296 } 297 tearDownBenchmark(b) 298 } 299 300 func BenchmarkGetCampaign1000(b *testing.B) { 301 setupBenchmark(b) 302 campaign := setupCampaign(b, 1000) 303 b.ResetTimer() 304 for i := 0; i < b.N; i++ { 305 _, err := GetCampaign(campaign.Id, campaign.UserId) 306 if err != nil { 307 b.Fatalf("error getting campaign: %v", err) 308 } 309 } 310 tearDownBenchmark(b) 311 } 312 313 func BenchmarkGetCampaign5000(b *testing.B) { 314 setupBenchmark(b) 315 campaign := setupCampaign(b, 5000) 316 b.ResetTimer() 317 for i := 0; i < b.N; i++ { 318 _, err := GetCampaign(campaign.Id, campaign.UserId) 319 if err != nil { 320 b.Fatalf("error getting campaign: %v", err) 321 } 322 } 323 tearDownBenchmark(b) 324 } 325 326 func BenchmarkGetCampaign10000(b *testing.B) { 327 setupBenchmark(b) 328 campaign := setupCampaign(b, 10000) 329 b.ResetTimer() 330 for i := 0; i < b.N; i++ { 331 _, err := GetCampaign(campaign.Id, campaign.UserId) 332 if err != nil { 333 b.Fatalf("error getting campaign: %v", err) 334 } 335 } 336 tearDownBenchmark(b) 337 }