github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+incompatible/app/plugin_deadlock_test.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  	"text/template"
    11  	"time"
    12  
    13  	"github.com/mattermost/mattermost-server/model"
    14  )
    15  
    16  func TestPluginDeadlock(t *testing.T) {
    17  	t.Run("Single Plugin", func(t *testing.T) {
    18  		th := Setup().InitBasic()
    19  		defer th.TearDown()
    20  
    21  		pluginPostOnActivate := template.Must(template.New("pluginPostOnActivate").Parse(`
    22  			package main
    23  
    24  			import (
    25  				"github.com/mattermost/mattermost-server/plugin"
    26  				"github.com/mattermost/mattermost-server/model"
    27  			)
    28  
    29  			type MyPlugin struct {
    30  				plugin.MattermostPlugin
    31  			}
    32  
    33  			func (p *MyPlugin) OnActivate() error {
    34  				_, err := p.API.CreatePost(&model.Post{
    35  					UserId: "{{.User.Id}}",
    36  					ChannelId: "{{.Channel.Id}}",
    37  					Message:   "message",
    38  				})
    39  				if err != nil {
    40  					panic(err.Error())
    41  				}
    42  
    43  				return nil
    44  			}
    45  
    46  			func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
    47  				if _, from_plugin := post.Props["from_plugin"]; from_plugin {
    48  					return nil, ""
    49  				}
    50  
    51  				p.API.CreatePost(&model.Post{
    52  					UserId: "{{.User.Id}}",
    53  					ChannelId: "{{.Channel.Id}}",
    54  					Message:   "message",
    55  					Props: map[string]interface{}{
    56  						"from_plugin": true,
    57  					},
    58  				})
    59  
    60  				return nil, ""
    61  			}
    62  
    63  			func main() {
    64  				plugin.ClientMain(&MyPlugin{})
    65  			}
    66  `,
    67  		))
    68  
    69  		templateData := struct {
    70  			User    *model.User
    71  			Channel *model.Channel
    72  		}{
    73  			th.BasicUser,
    74  			th.BasicChannel,
    75  		}
    76  
    77  		plugins := []string{}
    78  		pluginTemplates := []*template.Template{
    79  			pluginPostOnActivate,
    80  		}
    81  		for _, pluginTemplate := range pluginTemplates {
    82  			b := &strings.Builder{}
    83  			pluginTemplate.Execute(b, templateData)
    84  
    85  			plugins = append(plugins, b.String())
    86  		}
    87  
    88  		done := make(chan bool)
    89  		go func() {
    90  			SetAppEnvironmentWithPlugins(t, plugins, th.App, th.App.NewPluginAPI)
    91  			close(done)
    92  		}()
    93  
    94  		select {
    95  		case <-done:
    96  		case <-time.After(30 * time.Second):
    97  			t.Fatal("plugin failed to activate: likely deadlocked")
    98  			go func() {
    99  				time.Sleep(5 * time.Second)
   100  				os.Exit(1)
   101  			}()
   102  		}
   103  	})
   104  
   105  	t.Run("Multiple Plugins", func(t *testing.T) {
   106  		th := Setup().InitBasic()
   107  		defer th.TearDown()
   108  
   109  		pluginPostOnHasBeenPosted := template.Must(template.New("pluginPostOnHasBeenPosted").Parse(`
   110  			package main
   111  
   112  			import (
   113  				"github.com/mattermost/mattermost-server/plugin"
   114  				"github.com/mattermost/mattermost-server/model"
   115  			)
   116  
   117  			type MyPlugin struct {
   118  				plugin.MattermostPlugin
   119  			}
   120  
   121  			func (p *MyPlugin) MessageWillBePosted(c *plugin.Context, post *model.Post) (*model.Post, string) {
   122  				if _, from_plugin := post.Props["from_plugin"]; from_plugin {
   123  					return nil, ""
   124  				}
   125  
   126  				p.API.CreatePost(&model.Post{
   127  					UserId: "{{.User.Id}}",
   128  					ChannelId: "{{.Channel.Id}}",
   129  					Message:   "message",
   130  					Props: map[string]interface{}{
   131  						"from_plugin": true,
   132  					},
   133  				})
   134  
   135  				return nil, ""
   136  			}
   137  
   138  			func main() {
   139  				plugin.ClientMain(&MyPlugin{})
   140  			}
   141  `,
   142  		))
   143  
   144  		pluginPostOnActivate := template.Must(template.New("pluginPostOnActivate").Parse(`
   145  			package main
   146  
   147  			import (
   148  				"github.com/mattermost/mattermost-server/plugin"
   149  				"github.com/mattermost/mattermost-server/model"
   150  			)
   151  
   152  			type MyPlugin struct {
   153  				plugin.MattermostPlugin
   154  			}
   155  
   156  			func (p *MyPlugin) OnActivate() error {
   157  				_, err := p.API.CreatePost(&model.Post{
   158  					UserId: "{{.User.Id}}",
   159  					ChannelId: "{{.Channel.Id}}",
   160  					Message:   "message",
   161  				})
   162  				if err != nil {
   163  					panic(err.Error())
   164  				}
   165  
   166  				return nil
   167  			}
   168  
   169  			func main() {
   170  				plugin.ClientMain(&MyPlugin{})
   171  			}
   172  `,
   173  		))
   174  
   175  		templateData := struct {
   176  			User    *model.User
   177  			Channel *model.Channel
   178  		}{
   179  			th.BasicUser,
   180  			th.BasicChannel,
   181  		}
   182  
   183  		plugins := []string{}
   184  		pluginTemplates := []*template.Template{
   185  			pluginPostOnHasBeenPosted,
   186  			pluginPostOnActivate,
   187  		}
   188  		for _, pluginTemplate := range pluginTemplates {
   189  			b := &strings.Builder{}
   190  			pluginTemplate.Execute(b, templateData)
   191  
   192  			plugins = append(plugins, b.String())
   193  		}
   194  
   195  		done := make(chan bool)
   196  		go func() {
   197  			SetAppEnvironmentWithPlugins(t, plugins, th.App, th.App.NewPluginAPI)
   198  			close(done)
   199  		}()
   200  
   201  		select {
   202  		case <-done:
   203  		case <-time.After(30 * time.Second):
   204  			t.Fatal("plugin failed to activate: likely deadlocked")
   205  			go func() {
   206  				time.Sleep(5 * time.Second)
   207  				os.Exit(1)
   208  			}()
   209  		}
   210  	})
   211  }