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  }