github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/diagnostics_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  	"encoding/json"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/mattermost/mattermost-server/v5/model"
    18  )
    19  
    20  func TestPluginSetting(t *testing.T) {
    21  	settings := &model.PluginSettings{
    22  		Plugins: map[string]map[string]interface{}{
    23  			"test": {
    24  				"foo": "bar",
    25  			},
    26  		},
    27  	}
    28  	assert.Equal(t, "bar", pluginSetting(settings, "test", "foo", "asd"))
    29  	assert.Equal(t, "asd", pluginSetting(settings, "test", "qwe", "asd"))
    30  }
    31  
    32  func TestPluginActivated(t *testing.T) {
    33  	states := map[string]*model.PluginState{
    34  		"foo": {
    35  			Enable: true,
    36  		},
    37  		"bar": {
    38  			Enable: false,
    39  		},
    40  	}
    41  	assert.True(t, pluginActivated(states, "foo"))
    42  	assert.False(t, pluginActivated(states, "bar"))
    43  	assert.False(t, pluginActivated(states, "none"))
    44  }
    45  
    46  func TestPluginVersion(t *testing.T) {
    47  	plugins := []*model.BundleInfo{
    48  		{
    49  			Manifest: &model.Manifest{
    50  				Id:      "test.plugin",
    51  				Version: "1.2.3",
    52  			},
    53  		},
    54  		{
    55  			Manifest: &model.Manifest{
    56  				Id:      "test.plugin2",
    57  				Version: "4.5.6",
    58  			},
    59  		},
    60  	}
    61  	assert.Equal(t, "1.2.3", pluginVersion(plugins, "test.plugin"))
    62  	assert.Equal(t, "4.5.6", pluginVersion(plugins, "test.plugin2"))
    63  	assert.Empty(t, pluginVersion(plugins, "unknown.plugin"))
    64  }
    65  
    66  func TestRudderDiagnostics(t *testing.T) {
    67  	if testing.Short() {
    68  		t.SkipNow()
    69  	}
    70  
    71  	th := SetupWithCustomConfig(t, func(config *model.Config) {
    72  		*config.PluginSettings.Enable = false
    73  	})
    74  	defer th.TearDown()
    75  
    76  	type batch struct {
    77  		MessageId  string
    78  		UserId     string
    79  		Event      string
    80  		Timestamp  time.Time
    81  		Properties map[string]interface{}
    82  	}
    83  
    84  	type payload struct {
    85  		MessageId string
    86  		SentAt    time.Time
    87  		Batch     []batch
    88  		Context   struct {
    89  			Library struct {
    90  				Name    string
    91  				Version string
    92  			}
    93  		}
    94  	}
    95  
    96  	data := make(chan payload, 100)
    97  	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    98  		body, err := ioutil.ReadAll(r.Body)
    99  		require.NoError(t, err)
   100  
   101  		var p payload
   102  		err = json.Unmarshal(body, &p)
   103  		require.NoError(t, err)
   104  
   105  		data <- p
   106  	}))
   107  	defer server.Close()
   108  
   109  	marketplaceServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
   110  		res.WriteHeader(http.StatusOK)
   111  		json, err := json.Marshal([]*model.MarketplacePlugin{{
   112  			BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
   113  				Manifest: &model.Manifest{
   114  					Id: "testplugin",
   115  				},
   116  			},
   117  		}})
   118  		require.NoError(t, err)
   119  		res.Write(json)
   120  	}))
   121  
   122  	defer func() { marketplaceServer.Close() }()
   123  
   124  	diagnosticID := "test-diagnostic-id-12345"
   125  	th.App.SetDiagnosticId(diagnosticID)
   126  	th.Server.initDiagnostics(server.URL)
   127  
   128  	assertPayload := func(t *testing.T, actual payload, event string, properties map[string]interface{}) {
   129  		t.Helper()
   130  		assert.NotEmpty(t, actual.MessageId)
   131  		assert.False(t, actual.SentAt.IsZero())
   132  		if assert.Len(t, actual.Batch, 1) {
   133  			assert.NotEmpty(t, actual.Batch[0].MessageId, "message id should not be empty")
   134  			assert.Equal(t, diagnosticID, actual.Batch[0].UserId)
   135  			if event != "" {
   136  				assert.Equal(t, event, actual.Batch[0].Event)
   137  			}
   138  			assert.False(t, actual.Batch[0].Timestamp.IsZero(), "batch timestamp should not be the zero value")
   139  			if properties != nil {
   140  				assert.Equal(t, properties, actual.Batch[0].Properties)
   141  			}
   142  		}
   143  		assert.Equal(t, "analytics-go", actual.Context.Library.Name)
   144  		assert.Equal(t, "3.0.0", actual.Context.Library.Version)
   145  	}
   146  
   147  	collectInfo := func(info *[]string) {
   148  		t.Helper()
   149  		for {
   150  			select {
   151  			case result := <-data:
   152  				assertPayload(t, result, "", nil)
   153  				*info = append(*info, result.Batch[0].Event)
   154  			case <-time.After(time.Second * 1):
   155  				return
   156  			}
   157  		}
   158  	}
   159  
   160  	collectBatches := func(info *[]batch) {
   161  		t.Helper()
   162  		for {
   163  			select {
   164  			case result := <-data:
   165  				assertPayload(t, result, "", nil)
   166  				*info = append(*info, result.Batch[0])
   167  			case <-time.After(time.Second * 1):
   168  				return
   169  			}
   170  		}
   171  	}
   172  
   173  	// Should send a client identify message
   174  	select {
   175  	case identifyMessage := <-data:
   176  		assertPayload(t, identifyMessage, "", nil)
   177  	case <-time.After(time.Second * 1):
   178  		require.Fail(t, "Did not receive ID message")
   179  	}
   180  
   181  	t.Run("Send", func(t *testing.T) {
   182  		testValue := "test-send-value-6789"
   183  		th.App.Srv().SendDiagnostic("Testing Diagnostic", map[string]interface{}{
   184  			"hey": testValue,
   185  		})
   186  		select {
   187  		case result := <-data:
   188  			assertPayload(t, result, "Testing Diagnostic", map[string]interface{}{
   189  				"hey": testValue,
   190  			})
   191  		case <-time.After(time.Second * 1):
   192  			require.Fail(t, "Did not receive diagnostic")
   193  		}
   194  	})
   195  
   196  	// Plugins remain disabled at this point
   197  	t.Run("SendDailyDiagnosticsPluginsDisabled", func(t *testing.T) {
   198  		th.App.Srv().sendDailyDiagnostics(true)
   199  
   200  		var info []string
   201  		// Collect the info sent.
   202  		collectInfo(&info)
   203  
   204  		for _, item := range []string{
   205  			TRACK_CONFIG_SERVICE,
   206  			TRACK_CONFIG_TEAM,
   207  			TRACK_CONFIG_SQL,
   208  			TRACK_CONFIG_LOG,
   209  			TRACK_CONFIG_NOTIFICATION_LOG,
   210  			TRACK_CONFIG_FILE,
   211  			TRACK_CONFIG_RATE,
   212  			TRACK_CONFIG_EMAIL,
   213  			TRACK_CONFIG_PRIVACY,
   214  			TRACK_CONFIG_OAUTH,
   215  			TRACK_CONFIG_LDAP,
   216  			TRACK_CONFIG_COMPLIANCE,
   217  			TRACK_CONFIG_LOCALIZATION,
   218  			TRACK_CONFIG_SAML,
   219  			TRACK_CONFIG_PASSWORD,
   220  			TRACK_CONFIG_CLUSTER,
   221  			TRACK_CONFIG_METRICS,
   222  			TRACK_CONFIG_SUPPORT,
   223  			TRACK_CONFIG_NATIVEAPP,
   224  			TRACK_CONFIG_EXPERIMENTAL,
   225  			TRACK_CONFIG_ANALYTICS,
   226  			TRACK_CONFIG_PLUGIN,
   227  			TRACK_ACTIVITY,
   228  			TRACK_SERVER,
   229  			TRACK_CONFIG_MESSAGE_EXPORT,
   230  			// TRACK_PLUGINS,
   231  		} {
   232  			require.Contains(t, info, item)
   233  		}
   234  	})
   235  
   236  	// Enable plugins for the remainder of the tests.
   237  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PluginSettings.Enable = true })
   238  
   239  	t.Run("SendDailyDiagnostics", func(t *testing.T) {
   240  		th.App.Srv().sendDailyDiagnostics(true)
   241  
   242  		var info []string
   243  		// Collect the info sent.
   244  		collectInfo(&info)
   245  
   246  		for _, item := range []string{
   247  			TRACK_CONFIG_SERVICE,
   248  			TRACK_CONFIG_TEAM,
   249  			TRACK_CONFIG_SQL,
   250  			TRACK_CONFIG_LOG,
   251  			TRACK_CONFIG_NOTIFICATION_LOG,
   252  			TRACK_CONFIG_FILE,
   253  			TRACK_CONFIG_RATE,
   254  			TRACK_CONFIG_EMAIL,
   255  			TRACK_CONFIG_PRIVACY,
   256  			TRACK_CONFIG_OAUTH,
   257  			TRACK_CONFIG_LDAP,
   258  			TRACK_CONFIG_COMPLIANCE,
   259  			TRACK_CONFIG_LOCALIZATION,
   260  			TRACK_CONFIG_SAML,
   261  			TRACK_CONFIG_PASSWORD,
   262  			TRACK_CONFIG_CLUSTER,
   263  			TRACK_CONFIG_METRICS,
   264  			TRACK_CONFIG_SUPPORT,
   265  			TRACK_CONFIG_NATIVEAPP,
   266  			TRACK_CONFIG_EXPERIMENTAL,
   267  			TRACK_CONFIG_ANALYTICS,
   268  			TRACK_CONFIG_PLUGIN,
   269  			TRACK_ACTIVITY,
   270  			TRACK_SERVER,
   271  			TRACK_CONFIG_MESSAGE_EXPORT,
   272  			TRACK_PLUGINS,
   273  		} {
   274  			require.Contains(t, info, item)
   275  		}
   276  	})
   277  
   278  	t.Run("Diagnostics for Marketplace plugins is returned", func(t *testing.T) {
   279  		th.App.Srv().trackPluginConfig(th.App.Srv().Config(), marketplaceServer.URL)
   280  
   281  		var batches []batch
   282  		collectBatches(&batches)
   283  
   284  		for _, b := range batches {
   285  			if b.Event == TRACK_CONFIG_PLUGIN {
   286  				assert.Contains(t, b.Properties, "enable_testplugin")
   287  				assert.Contains(t, b.Properties, "version_testplugin")
   288  
   289  				// Confirm known plugins are not present
   290  				assert.NotContains(t, b.Properties, "enable_jira")
   291  				assert.NotContains(t, b.Properties, "version_jira")
   292  			}
   293  		}
   294  	})
   295  
   296  	t.Run("Diagnostics for known plugins is returned, if request to Marketplace fails", func(t *testing.T) {
   297  		th.App.Srv().trackPluginConfig(th.App.Srv().Config(), "http://some.random.invalid.url")
   298  
   299  		var batches []batch
   300  		collectBatches(&batches)
   301  
   302  		for _, b := range batches {
   303  			if b.Event == TRACK_CONFIG_PLUGIN {
   304  				assert.NotContains(t, b.Properties, "enable_testplugin")
   305  				assert.NotContains(t, b.Properties, "version_testplugin")
   306  
   307  				// Confirm known plugins are present
   308  				assert.Contains(t, b.Properties, "enable_jira")
   309  				assert.Contains(t, b.Properties, "version_jira")
   310  			}
   311  		}
   312  	})
   313  
   314  	t.Run("SendDailyDiagnosticsNoRudderKey", func(t *testing.T) {
   315  		th.App.Srv().SendDailyDiagnostics()
   316  
   317  		select {
   318  		case <-data:
   319  			require.Fail(t, "Should not send diagnostics when the rudder key is not set")
   320  		case <-time.After(time.Second * 1):
   321  			// Did not receive diagnostics
   322  		}
   323  	})
   324  
   325  	t.Run("SendDailyDiagnosticsDisabled", func(t *testing.T) {
   326  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.LogSettings.EnableDiagnostics = false })
   327  
   328  		th.App.Srv().sendDailyDiagnostics(true)
   329  
   330  		select {
   331  		case <-data:
   332  			require.Fail(t, "Should not send diagnostics when they are disabled")
   333  		case <-time.After(time.Second * 1):
   334  			// Did not receive diagnostics
   335  		}
   336  	})
   337  }