github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/app/server_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bufio"
     8  	"crypto/tls"
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	"net"
    14  	"net/http"
    15  	"net/http/httptest"
    16  	"os"
    17  	"path"
    18  	"strconv"
    19  	"strings"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/getsentry/sentry-go"
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"github.com/mattermost/mattermost-server/v5/config"
    28  	"github.com/mattermost/mattermost-server/v5/mlog"
    29  	"github.com/mattermost/mattermost-server/v5/model"
    30  	"github.com/mattermost/mattermost-server/v5/store/storetest"
    31  	"github.com/mattermost/mattermost-server/v5/utils/fileutils"
    32  )
    33  
    34  func TestStartServerSuccess(t *testing.T) {
    35  	s, err := NewServer()
    36  	require.NoError(t, err)
    37  
    38  	s.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
    39  	serverErr := s.Start()
    40  
    41  	client := &http.Client{}
    42  	checkEndpoint(t, client, "http://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
    43  
    44  	s.Shutdown()
    45  	require.NoError(t, serverErr)
    46  }
    47  
    48  func TestReadReplicaDisabledBasedOnLicense(t *testing.T) {
    49  	t.Skip("TODO: fix flaky test")
    50  	cfg := model.Config{}
    51  	cfg.SetDefaults()
    52  	driverName := os.Getenv("MM_SQLSETTINGS_DRIVERNAME")
    53  	if driverName == "" {
    54  		driverName = model.DATABASE_DRIVER_POSTGRES
    55  	}
    56  	dsn := ""
    57  	if driverName == model.DATABASE_DRIVER_POSTGRES {
    58  		dsn = os.Getenv("TEST_DATABASE_POSTGRESQL_DSN")
    59  	} else {
    60  		dsn = os.Getenv("TEST_DATABASE_MYSQL_DSN")
    61  	}
    62  	cfg.SqlSettings = *storetest.MakeSqlSettings(driverName)
    63  	if dsn != "" {
    64  		cfg.SqlSettings.DataSource = &dsn
    65  	}
    66  	cfg.SqlSettings.DataSourceReplicas = []string{*cfg.SqlSettings.DataSource}
    67  	cfg.SqlSettings.DataSourceSearchReplicas = []string{*cfg.SqlSettings.DataSource}
    68  
    69  	t.Run("Read Replicas with no License", func(t *testing.T) {
    70  		s, err := NewServer(func(server *Server) error {
    71  			configStore := config.NewTestMemoryStore()
    72  			configStore.Set(&cfg)
    73  			server.configStore = configStore
    74  			return nil
    75  		})
    76  		require.NoError(t, err)
    77  		defer s.Shutdown()
    78  		require.Same(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica())
    79  		require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1)
    80  	})
    81  
    82  	t.Run("Read Replicas With License", func(t *testing.T) {
    83  		s, err := NewServer(func(server *Server) error {
    84  			configStore := config.NewTestMemoryStore()
    85  			configStore.Set(&cfg)
    86  			server.licenseValue.Store(model.NewTestLicense())
    87  			return nil
    88  		})
    89  		require.NoError(t, err)
    90  		defer s.Shutdown()
    91  		require.NotSame(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica())
    92  		require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1)
    93  	})
    94  
    95  	t.Run("Search Replicas with no License", func(t *testing.T) {
    96  		s, err := NewServer(func(server *Server) error {
    97  			configStore := config.NewTestMemoryStore()
    98  			configStore.Set(&cfg)
    99  			server.configStore = configStore
   100  			return nil
   101  		})
   102  		require.NoError(t, err)
   103  		defer s.Shutdown()
   104  		require.Same(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica())
   105  		require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1)
   106  	})
   107  
   108  	t.Run("Search Replicas With License", func(t *testing.T) {
   109  		s, err := NewServer(func(server *Server) error {
   110  			configStore := config.NewTestMemoryStore()
   111  			configStore.Set(&cfg)
   112  			server.configStore = configStore
   113  			server.licenseValue.Store(model.NewTestLicense())
   114  			return nil
   115  		})
   116  		require.NoError(t, err)
   117  		defer s.Shutdown()
   118  		require.NotSame(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica())
   119  		require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1)
   120  	})
   121  }
   122  
   123  func TestStartServerPortUnavailable(t *testing.T) {
   124  	s, err := NewServer()
   125  	require.NoError(t, err)
   126  
   127  	// Listen on the next available port
   128  	listener, err := net.Listen("tcp", ":0")
   129  	require.NoError(t, err)
   130  
   131  	// Attempt to listen on the port used above.
   132  	s.UpdateConfig(func(cfg *model.Config) {
   133  		*cfg.ServiceSettings.ListenAddress = listener.Addr().String()
   134  	})
   135  
   136  	serverErr := s.Start()
   137  	s.Shutdown()
   138  	require.Error(t, serverErr)
   139  }
   140  
   141  func TestStartServerTLSSuccess(t *testing.T) {
   142  	s, err := NewServer()
   143  	require.NoError(t, err)
   144  
   145  	testDir, _ := fileutils.FindDir("tests")
   146  	s.UpdateConfig(func(cfg *model.Config) {
   147  		*cfg.ServiceSettings.ListenAddress = ":0"
   148  		*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   149  		*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   150  		*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   151  	})
   152  	serverErr := s.Start()
   153  
   154  	tr := &http.Transport{
   155  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   156  	}
   157  
   158  	client := &http.Client{Transport: tr}
   159  	checkEndpoint(t, client, "https://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
   160  
   161  	s.Shutdown()
   162  	require.NoError(t, serverErr)
   163  }
   164  
   165  func TestDatabaseTypeAndMattermostVersion(t *testing.T) {
   166  	sqlDrivernameEnvironment := os.Getenv("MM_SQLSETTINGS_DRIVERNAME")
   167  	defer os.Setenv("MM_SQLSETTINGS_DRIVERNAME", sqlDrivernameEnvironment)
   168  
   169  	os.Setenv("MM_SQLSETTINGS_DRIVERNAME", "postgres")
   170  
   171  	th := Setup(t)
   172  	defer th.TearDown()
   173  
   174  	databaseType, mattermostVersion := th.Server.DatabaseTypeAndMattermostVersion()
   175  	assert.Equal(t, "postgres", databaseType)
   176  	assert.Equal(t, "5.31.0", mattermostVersion)
   177  
   178  	os.Setenv("MM_SQLSETTINGS_DRIVERNAME", "mysql")
   179  
   180  	th2 := Setup(t)
   181  	defer th2.TearDown()
   182  
   183  	databaseType, mattermostVersion = th2.Server.DatabaseTypeAndMattermostVersion()
   184  	assert.Equal(t, "mysql", databaseType)
   185  	assert.Equal(t, "5.31.0", mattermostVersion)
   186  }
   187  
   188  func TestGenerateSupportPacket(t *testing.T) {
   189  	th := Setup(t)
   190  	defer th.TearDown()
   191  
   192  	d1 := []byte("hello\ngo\n")
   193  	err := ioutil.WriteFile("mattermost.log", d1, 0777)
   194  	require.NoError(t, err)
   195  	err = ioutil.WriteFile("notifications.log", d1, 0777)
   196  	require.NoError(t, err)
   197  
   198  	fileDatas := th.App.GenerateSupportPacket()
   199  	testFiles := []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "mattermost.log", "notifications.log"}
   200  	for i, fileData := range fileDatas {
   201  		require.NotNil(t, fileData)
   202  		assert.Equal(t, testFiles[i], fileData.Filename)
   203  		assert.Positive(t, len(fileData.Body))
   204  	}
   205  
   206  	// Remove these two files and ensure that warning.txt file is generated
   207  	err = os.Remove("notifications.log")
   208  	require.NoError(t, err)
   209  	err = os.Remove("mattermost.log")
   210  	require.NoError(t, err)
   211  	fileDatas = th.App.GenerateSupportPacket()
   212  	testFiles = []string{"support_packet.yaml", "plugins.json", "sanitized_config.json", "warning.txt"}
   213  	for i, fileData := range fileDatas {
   214  		require.NotNil(t, fileData)
   215  		assert.Equal(t, testFiles[i], fileData.Filename)
   216  		assert.Positive(t, len(fileData.Body))
   217  	}
   218  }
   219  
   220  func TestGetNotificationsLog(t *testing.T) {
   221  	th := Setup(t)
   222  	defer th.TearDown()
   223  
   224  	// Disable notifications file to get an error
   225  	th.App.UpdateConfig(func(cfg *model.Config) {
   226  		*cfg.NotificationLogSettings.EnableFile = false
   227  	})
   228  
   229  	fileData, warning := th.App.getNotificationsLog()
   230  	assert.Nil(t, fileData)
   231  	assert.Equal(t, warning, "Unable to retrieve notifications.log because LogSettings: EnableFile is false in config.json")
   232  
   233  	// Enable notifications file but delete any notifications file to get an error trying to read the file
   234  	th.App.UpdateConfig(func(cfg *model.Config) {
   235  		*cfg.NotificationLogSettings.EnableFile = true
   236  	})
   237  
   238  	// If any previous notifications.log file, lets delete it
   239  	os.Remove("notifications.log")
   240  
   241  	fileData, warning = th.App.getNotificationsLog()
   242  	assert.Nil(t, fileData)
   243  	assert.Contains(t, warning, "ioutil.ReadFile(notificationsLog) Error:")
   244  
   245  	// Happy path where we have file and no warning
   246  	d1 := []byte("hello\ngo\n")
   247  	err := ioutil.WriteFile("notifications.log", d1, 0777)
   248  	defer os.Remove("notifications.log")
   249  	require.NoError(t, err)
   250  
   251  	fileData, warning = th.App.getNotificationsLog()
   252  	require.NotNil(t, fileData)
   253  	assert.Equal(t, "notifications.log", fileData.Filename)
   254  	assert.Positive(t, len(fileData.Body))
   255  	assert.Empty(t, warning)
   256  }
   257  
   258  func TestGetMattermostLog(t *testing.T) {
   259  	th := Setup(t)
   260  	defer th.TearDown()
   261  
   262  	// disable mattermost log file setting in config so we should get an warning
   263  	th.App.UpdateConfig(func(cfg *model.Config) {
   264  		*cfg.LogSettings.EnableFile = false
   265  	})
   266  
   267  	fileData, warning := th.App.getMattermostLog()
   268  	assert.Nil(t, fileData)
   269  	assert.Equal(t, "Unable to retrieve mattermost.log because LogSettings: EnableFile is false in config.json", warning)
   270  
   271  	// We enable the setting but delete any mattermost log file
   272  	th.App.UpdateConfig(func(cfg *model.Config) {
   273  		*cfg.LogSettings.EnableFile = true
   274  	})
   275  
   276  	// If any previous mattermost.log file, lets delete it
   277  	os.Remove("mattermost.log")
   278  
   279  	fileData, warning = th.App.getMattermostLog()
   280  	assert.Nil(t, fileData)
   281  	assert.Contains(t, warning, "ioutil.ReadFile(mattermostLog) Error:")
   282  
   283  	// Happy path where we get a log file and no warning
   284  	d1 := []byte("hello\ngo\n")
   285  	err := ioutil.WriteFile("mattermost.log", d1, 0777)
   286  	defer os.Remove("mattermost.log")
   287  	require.NoError(t, err)
   288  
   289  	fileData, warning = th.App.getMattermostLog()
   290  	require.NotNil(t, fileData)
   291  	assert.Equal(t, "mattermost.log", fileData.Filename)
   292  	assert.Positive(t, len(fileData.Body))
   293  	assert.Empty(t, warning)
   294  }
   295  
   296  func TestCreateSanitizedConfigFile(t *testing.T) {
   297  	th := Setup(t)
   298  	defer th.TearDown()
   299  
   300  	// Happy path where we have a sanitized config file with no warning
   301  	fileData, warning := th.App.createSanitizedConfigFile()
   302  	require.NotNil(t, fileData)
   303  	assert.Equal(t, "sanitized_config.json", fileData.Filename)
   304  	assert.Positive(t, len(fileData.Body))
   305  	assert.Empty(t, warning)
   306  }
   307  
   308  func TestCreatePluginsFile(t *testing.T) {
   309  	th := Setup(t)
   310  	defer th.TearDown()
   311  
   312  	// Happy path where we have a plugins file with no warning
   313  	fileData, warning := th.App.createPluginsFile()
   314  	require.NotNil(t, fileData)
   315  	assert.Equal(t, "plugins.json", fileData.Filename)
   316  	assert.Positive(t, len(fileData.Body))
   317  	assert.Empty(t, warning)
   318  
   319  	// Turn off plugins so we can get an error
   320  	th.App.UpdateConfig(func(cfg *model.Config) {
   321  		*cfg.PluginSettings.Enable = false
   322  	})
   323  
   324  	// Plugins off in settings so no fileData and we get a warning instead
   325  	fileData, warning = th.App.createPluginsFile()
   326  	assert.Nil(t, fileData)
   327  	assert.Contains(t, warning, "c.App.GetPlugins() Error:")
   328  }
   329  
   330  func TestGenerateSupportPacketYaml(t *testing.T) {
   331  	th := Setup(t)
   332  	defer th.TearDown()
   333  
   334  	// Happy path where we have a support packet yaml file without any warnings
   335  	fileData, warning := th.App.generateSupportPacketYaml()
   336  	require.NotNil(t, fileData)
   337  	assert.Equal(t, "support_packet.yaml", fileData.Filename)
   338  	assert.Positive(t, len(fileData.Body))
   339  	assert.Empty(t, warning)
   340  
   341  }
   342  
   343  func TestStartServerTLSVersion(t *testing.T) {
   344  	s, err := NewServer()
   345  	require.NoError(t, err)
   346  
   347  	testDir, _ := fileutils.FindDir("tests")
   348  	s.UpdateConfig(func(cfg *model.Config) {
   349  		*cfg.ServiceSettings.ListenAddress = ":0"
   350  		*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   351  		*cfg.ServiceSettings.TLSMinVer = "1.2"
   352  		*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   353  		*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   354  	})
   355  	serverErr := s.Start()
   356  
   357  	tr := &http.Transport{
   358  		TLSClientConfig: &tls.Config{
   359  			InsecureSkipVerify: true,
   360  			MaxVersion:         tls.VersionTLS11,
   361  		},
   362  	}
   363  
   364  	client := &http.Client{Transport: tr}
   365  	err = checkEndpoint(t, client, "https://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
   366  
   367  	if !strings.Contains(err.Error(), "remote error: tls: protocol version not supported") {
   368  		t.Errorf("Expected protocol version error, got %s", err)
   369  	}
   370  
   371  	client.Transport = &http.Transport{
   372  		TLSClientConfig: &tls.Config{
   373  			InsecureSkipVerify: true,
   374  		},
   375  	}
   376  
   377  	err = checkEndpoint(t, client, "https://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
   378  
   379  	if err != nil {
   380  		t.Errorf("Expected nil, got %s", err)
   381  	}
   382  
   383  	s.Shutdown()
   384  	require.NoError(t, serverErr)
   385  }
   386  
   387  func TestStartServerTLSOverwriteCipher(t *testing.T) {
   388  	s, err := NewServer()
   389  	require.NoError(t, err)
   390  
   391  	testDir, _ := fileutils.FindDir("tests")
   392  	s.UpdateConfig(func(cfg *model.Config) {
   393  		*cfg.ServiceSettings.ListenAddress = ":0"
   394  		*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   395  		cfg.ServiceSettings.TLSOverwriteCiphers = []string{
   396  			"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
   397  			"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
   398  		}
   399  		*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   400  		*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   401  	})
   402  	serverErr := s.Start()
   403  
   404  	tr := &http.Transport{
   405  		TLSClientConfig: &tls.Config{
   406  			InsecureSkipVerify: true,
   407  			CipherSuites: []uint16{
   408  				tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
   409  			},
   410  			MaxVersion: tls.VersionTLS12,
   411  		},
   412  	}
   413  
   414  	client := &http.Client{Transport: tr}
   415  	err = checkEndpoint(t, client, "https://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
   416  	require.Error(t, err, "Expected error due to Cipher mismatch")
   417  	if !strings.Contains(err.Error(), "remote error: tls: handshake failure") {
   418  		t.Errorf("Expected protocol version error, got %s", err)
   419  	}
   420  
   421  	client.Transport = &http.Transport{
   422  		TLSClientConfig: &tls.Config{
   423  			InsecureSkipVerify: true,
   424  			CipherSuites: []uint16{
   425  				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   426  				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   427  			},
   428  			MaxVersion: tls.VersionTLS12,
   429  		},
   430  	}
   431  
   432  	err = checkEndpoint(t, client, "https://localhost:"+strconv.Itoa(s.ListenAddr.Port)+"/", http.StatusNotFound)
   433  
   434  	if err != nil {
   435  		t.Errorf("Expected nil, got %s", err)
   436  	}
   437  
   438  	s.Shutdown()
   439  	require.NoError(t, serverErr)
   440  }
   441  
   442  func checkEndpoint(t *testing.T, client *http.Client, url string, expectedStatus int) error {
   443  	res, err := client.Get(url)
   444  
   445  	if err != nil {
   446  		return err
   447  	}
   448  
   449  	defer res.Body.Close()
   450  
   451  	if res.StatusCode != expectedStatus {
   452  		t.Errorf("Response code was %d; want %d", res.StatusCode, expectedStatus)
   453  	}
   454  
   455  	return nil
   456  }
   457  
   458  func TestPanicLog(t *testing.T) {
   459  	// Creating a temp file to collect logs
   460  	tmpfile, err := ioutil.TempFile("", "mlog")
   461  	if err != nil {
   462  		require.NoError(t, err)
   463  	}
   464  
   465  	defer func() {
   466  		require.NoError(t, tmpfile.Close())
   467  		require.NoError(t, os.Remove(tmpfile.Name()))
   468  	}()
   469  
   470  	// This test requires Zap file target for now.
   471  	mlog.EnableZap()
   472  	defer mlog.DisableZap()
   473  
   474  	// Creating logger to log to console and temp file
   475  	logger := mlog.NewLogger(&mlog.LoggerConfiguration{
   476  		EnableConsole: true,
   477  		ConsoleJson:   true,
   478  		EnableFile:    true,
   479  		FileLocation:  tmpfile.Name(),
   480  		FileLevel:     mlog.LevelInfo,
   481  	})
   482  
   483  	// Creating a server with logger
   484  	s, err := NewServer(SetLogger(logger))
   485  	require.NoError(t, err)
   486  
   487  	// Route for just panicing
   488  	s.Router.HandleFunc("/panic", func(writer http.ResponseWriter, request *http.Request) {
   489  		s.Log.Info("inside panic handler")
   490  		panic("log this panic")
   491  	})
   492  
   493  	testDir, _ := fileutils.FindDir("tests")
   494  	s.UpdateConfig(func(cfg *model.Config) {
   495  		*cfg.ServiceSettings.ListenAddress = ":0"
   496  		*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   497  		*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   498  		*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   499  	})
   500  	serverErr := s.Start()
   501  	require.NoError(t, serverErr)
   502  
   503  	// Calling panic route
   504  	tr := &http.Transport{
   505  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   506  	}
   507  
   508  	client := &http.Client{Transport: tr}
   509  	client.Get("https://localhost:" + strconv.Itoa(s.ListenAddr.Port) + "/panic")
   510  	s.Shutdown()
   511  
   512  	// Checking whether panic was logged
   513  	var panicLogged = false
   514  	var infoLogged = false
   515  
   516  	_, err = tmpfile.Seek(0, 0)
   517  	require.NoError(t, err)
   518  
   519  	scanner := bufio.NewScanner(tmpfile)
   520  	for scanner.Scan() {
   521  		if !infoLogged && strings.Contains(scanner.Text(), "inside panic handler") {
   522  			infoLogged = true
   523  		}
   524  		if strings.Contains(scanner.Text(), "log this panic") {
   525  			panicLogged = true
   526  			break
   527  		}
   528  	}
   529  
   530  	if !infoLogged {
   531  		t.Error("Info log line was supposed to be logged")
   532  	}
   533  
   534  	if !panicLogged {
   535  		t.Error("Panic was supposed to be logged")
   536  	}
   537  }
   538  
   539  func TestSentry(t *testing.T) {
   540  	if testing.Short() {
   541  		t.SkipNow()
   542  	}
   543  
   544  	client := &http.Client{Timeout: 5 * time.Second, Transport: &http.Transport{
   545  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   546  	}}
   547  	testDir, _ := fileutils.FindDir("tests")
   548  
   549  	t.Run("sentry is disabled, should not receive a report", func(t *testing.T) {
   550  		data := make(chan bool, 1)
   551  
   552  		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   553  			t.Log("Received sentry request for some reason")
   554  			data <- true
   555  		}))
   556  		defer server.Close()
   557  
   558  		// make sure we don't report anything when sentry is disabled
   559  		_, port, _ := net.SplitHostPort(server.Listener.Addr().String())
   560  		dsn, err := sentry.NewDsn(fmt.Sprintf("http://test:test@localhost:%s/123", port))
   561  		require.NoError(t, err)
   562  		SentryDSN = dsn.String()
   563  
   564  		s, err := NewServer(func(server *Server) error {
   565  			configStore, _ := config.NewFileStore("config.json", true)
   566  			store, _ := config.NewStoreFromBacking(configStore, nil, false)
   567  			server.configStore = store
   568  			server.UpdateConfig(func(cfg *model.Config) {
   569  				*cfg.ServiceSettings.ListenAddress = ":0"
   570  				*cfg.LogSettings.EnableSentry = false
   571  				*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   572  				*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   573  				*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   574  				*cfg.LogSettings.EnableDiagnostics = true
   575  			})
   576  			return nil
   577  		})
   578  		require.NoError(t, err)
   579  
   580  		// Route for just panicing
   581  		s.Router.HandleFunc("/panic", func(writer http.ResponseWriter, request *http.Request) {
   582  			panic("log this panic")
   583  		})
   584  
   585  		require.NoError(t, s.Start())
   586  		defer s.Shutdown()
   587  
   588  		resp, err := client.Get("https://localhost:" + strconv.Itoa(s.ListenAddr.Port) + "/panic")
   589  		require.Nil(t, resp)
   590  		require.True(t, errors.Is(err, io.EOF), fmt.Sprintf("unexpected error: %s", err))
   591  
   592  		sentry.Flush(time.Second)
   593  		select {
   594  		case <-data:
   595  			require.Fail(t, "Sentry received a message, even though it's disabled!")
   596  		case <-time.After(time.Second):
   597  			t.Log("Sentry request didn't arrive. Good!")
   598  		}
   599  	})
   600  
   601  	t.Run("sentry is enabled, report should be received", func(t *testing.T) {
   602  		data := make(chan bool, 1)
   603  
   604  		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   605  			t.Log("Received sentry request!")
   606  			data <- true
   607  		}))
   608  		defer server.Close()
   609  
   610  		_, port, _ := net.SplitHostPort(server.Listener.Addr().String())
   611  		dsn, err := sentry.NewDsn(fmt.Sprintf("http://test:test@localhost:%s/123", port))
   612  		require.NoError(t, err)
   613  		SentryDSN = dsn.String()
   614  
   615  		s, err := NewServer(func(server *Server) error {
   616  			configStore, _ := config.NewFileStore("config.json", true)
   617  			store, _ := config.NewStoreFromBacking(configStore, nil, false)
   618  			server.configStore = store
   619  			server.UpdateConfig(func(cfg *model.Config) {
   620  				*cfg.ServiceSettings.ListenAddress = ":0"
   621  				*cfg.ServiceSettings.ConnectionSecurity = "TLS"
   622  				*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
   623  				*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
   624  				*cfg.LogSettings.EnableSentry = true
   625  				*cfg.LogSettings.EnableDiagnostics = true
   626  			})
   627  			return nil
   628  		})
   629  		require.NoError(t, err)
   630  
   631  		// Route for just panicing
   632  		s.Router.HandleFunc("/panic", func(writer http.ResponseWriter, request *http.Request) {
   633  			panic("log this panic")
   634  		})
   635  
   636  		require.NoError(t, s.Start())
   637  		defer s.Shutdown()
   638  
   639  		resp, err := client.Get("https://localhost:" + strconv.Itoa(s.ListenAddr.Port) + "/panic")
   640  		require.Nil(t, resp)
   641  		require.True(t, errors.Is(err, io.EOF), fmt.Sprintf("unexpected error: %s", err))
   642  
   643  		sentry.Flush(time.Second)
   644  		select {
   645  		case <-data:
   646  			t.Log("Sentry request arrived. Good!")
   647  		case <-time.After(time.Second * 10):
   648  			require.Fail(t, "Sentry report didn't arrive")
   649  		}
   650  	})
   651  }