// TestNewPinger tests building the pinger object.
func TestNewPinger(t *testing.T) {
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	p := pinger.NewPinger(db, pinger.GetSitesMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)

	if len(p.Sites) != 3 {
		t.Fatal("Incorrect number of sites returned in new pinger.")
	}

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "SITE: Test, http://www.google.com") {
		t.Fatal("Failed to load first site.")
	}
	if !strings.Contains(results, "SITE: Test 2, http://www.github.com") {
		t.Fatal("Failed to load second site.")
	}
	if !strings.Contains(results, "SITE: Test 3, http://www.test.com") {
		t.Fatal("Failed to load third site.")
	}
}
// TestStartAndRestartPinger starts up the pinger and then stops it after 3 seconds
func TestStartAndRestartPinger(t *testing.T) {
	// Fake db for testing.
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	pinger.ResetHitCount()
	p := pinger.NewPinger(db, pinger.GetSitesMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()
	// Sleep to allow running the tests before stopping.
	time.Sleep(5 * time.Second)
	p.Stop() // Test Restart after stop
	p.Start()
	p.Stop()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Client.Timeout") {
		t.Errorf("Failed to report timeout error.")
	}
	if !strings.Contains(results, "Test 3 Paused") {
		t.Errorf("Failed to report paused site.")
	}
	if !strings.Contains(results, "Error - HTTP Status Code") {
		t.Fatal("Failed to report bad HTTP Status Code.")
	}
	if !strings.Contains(results, "Sending Notification of Site Contacts about Test 2: Site is Down...") {
		t.Fatal("Failed to report site being down.")
	}
	if !strings.Contains(results, "Will notify status change for Test 2: Test 2 at http://www.github.com: Site is now up, response time was 300ms.") {
		t.Fatal("Failed to report change in notification.")
	}
}
// TestStartPingerErrorWithGetSites verifies that an error is handled when the get sites returns
// an error.
func TestStartPingerErrorWithGetSites(t *testing.T) {
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	pinger.ResetHitCount()
	p := pinger.NewPinger(db, pinger.GetSitesErrorMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Timeout accessing the SQL database.") {
		t.Fatal("Failed to report error getting the sites from the DB.")
	}
}
// TestStartEmptySitesPinger verifies that proper reporting is done for the case of no active sites.
func TestStartEmptySitesPinger(t *testing.T) {
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	pinger.ResetHitCount()
	p := pinger.NewPinger(db, pinger.GetEmptySitesMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "No active sites set up for pinging in the database!") {
		t.Fatal("Failed to report empty sites.")
	}
}
// TestNotifyError tests calling the Notifications with errors on each send method.
func TestNotifyError(t *testing.T) {
	site := getTestSite()
	n := notifier.NewNotifier(site, "Site 1 responding OK", "Site 1 Up", notifier.SendEmailErrorMock, notifier.SendSmsErrorMock)
	n.Notify()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Error sending SMS: Error - no response from server.") {
		t.Error("Failed to report error in SMS send to Jack Contact.")
	}

	if !strings.Contains(results, "Error sending email: Error - no response from server.") {
		t.Error("Failed to report error in email send to Joe Contact.")
	}
}
// TestNotify tests calling the Notifications successfully.
func TestNotify(t *testing.T) {
	pinger.CreatePingerLog("", true)
	site := getTestSite()
	n := notifier.NewNotifier(site, "Site 1 responding OK", "Site 1 Up", notifier.SendEmailMock, notifier.SendSmsMock)
	n.Notify()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Sending notifications for Jack Contact Site 1 Up Site 1 responding OK") {
		t.Error("Failed to report successful send to Jack Contact.")
	}

	if !strings.Contains(results, "Sending notifications for Joe Contact Site 1 Up Site 1 responding OK") {
		t.Error("Failed to report successful send to Joe Contact.")
	}
}
// TestInternetAccessError starts up the pinger and then stops it after 3 seconds
func TestInternetAccessError(t *testing.T) {
	// Fake db for testing.
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	p := pinger.NewPinger(db, pinger.GetSitesMock, pinger.RequestURLBadInternetAccessMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()
	time.Sleep(5 * time.Second)
	p.Stop()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Unable to determine site status - connect: network is unreachable") {
		t.Fatal("Failed to report Internet Access Error: ", results)
	}
}
// TestUpdateSiteSettings starts up the pinger and then updates the site settings.
func TestUpdateSiteSettings(t *testing.T) {
	// Fake db for testing.
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	pinger.ResetHitCount()
	p := pinger.NewPinger(db, pinger.GetSitesMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()
	// Test UpdateSiteSettings
	p.UpdateSiteSettings()
	p.Stop()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}
	if !strings.Contains(results, "Updating the site settings due to change...") {
		t.Fatal("Failed to launch update site settings.")
	}
}
// TestContentCheck tests the content checks (Must Include and Must Not Include)
func TestContentCheck(t *testing.T) {
	// Fake db for testing.
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	p := pinger.NewPinger(db, pinger.GetSitesContentMock, pinger.RequestURLContentMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()
	// Sleep to allow running the tests before stopping.
	time.Sleep(2 * time.Second)
	p.Stop()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Error - body content content has excluded content:  Bad response text") {
		t.Fatal("Failed to report excluded content.")
	}

	if !strings.Contains(results, "Error - required body content missing:  Good response text") {
		t.Fatal("Failed to report missing required content.")
	}
}
// TestUpdateSiteSettingsError tests when UpdateSiteSettings returns a DB error.
func TestUpdateSiteSettingsError(t *testing.T) {
	// Fake db for testing.
	db, _ := sql.Open("testdb", "")
	pinger.CreatePingerLog("", true)
	pinger.ResetHitCount()
	p := pinger.NewPinger(db, pinger.GetSitesErrorMock, pinger.RequestURLMock,
		notifier.SendEmailMock, notifier.SendSmsMock)
	p.Start()
	// Test UpdateSiteSettings with error due to database.
	err := p.UpdateSiteSettings()
	if err == nil {
		t.Error("Failed to report error with getting site settings.")
	}
	p.Stop()

	results, err := pinger.GetLogContent()
	if err != nil {
		t.Fatal("Failed to get log results.", err)
	}

	if !strings.Contains(results, "Timeout accessing the SQL database.") {
		t.Fatal("Failed to report problem updating the sites.")
	}
}