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

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package testlib
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  
    13  	"github.com/pkg/errors"
    14  
    15  	"github.com/mattermost/mattermost-server/v5/model"
    16  	"github.com/mattermost/mattermost-server/v5/services/filesstore"
    17  	"github.com/mattermost/mattermost-server/v5/utils"
    18  	"github.com/mattermost/mattermost-server/v5/utils/fileutils"
    19  )
    20  
    21  const (
    22  	resourceTypeFile = iota
    23  	resourceTypeFolder
    24  )
    25  
    26  const (
    27  	actionCopy = iota
    28  	actionSymlink
    29  )
    30  
    31  const root = "___mattermost-server"
    32  
    33  type testResourceDetails struct {
    34  	src     string
    35  	dest    string
    36  	resType int8
    37  	action  int8
    38  }
    39  
    40  // getCommonBaseSearchPaths() is a custom version of what fileutils exposes. At some point, consolidate.
    41  func getCommonBaseSearchPaths() []string {
    42  	paths := []string{
    43  		".",
    44  		"..",
    45  		"../..",
    46  		"../../..",
    47  		"../../../..",
    48  	}
    49  
    50  	// this enables the server to be used in tests from a different repository
    51  	if mmPath := os.Getenv("MM_SERVER_PATH"); mmPath != "" {
    52  		paths = append(paths, mmPath)
    53  	}
    54  
    55  	return paths
    56  }
    57  
    58  func findFile(path string) string {
    59  	return fileutils.FindPath(path, getCommonBaseSearchPaths(), func(fileInfo os.FileInfo) bool {
    60  		return !fileInfo.IsDir()
    61  	})
    62  }
    63  
    64  func findDir(dir string) (string, bool) {
    65  	if dir == root {
    66  		srcPath := findFile("go.mod")
    67  		if srcPath == "" {
    68  			return "./", false
    69  		}
    70  
    71  		return path.Dir(srcPath), true
    72  	}
    73  
    74  	found := fileutils.FindPath(dir, getCommonBaseSearchPaths(), func(fileInfo os.FileInfo) bool {
    75  		return fileInfo.IsDir()
    76  	})
    77  	if found == "" {
    78  		return "./", false
    79  	}
    80  
    81  	return found, true
    82  }
    83  
    84  func getTestResourcesToSetup() []testResourceDetails {
    85  	var srcPath string
    86  	var found bool
    87  
    88  	var testResourcesToSetup = []testResourceDetails{
    89  		{root, "mattermost-server", resourceTypeFolder, actionSymlink},
    90  		{"i18n", "i18n", resourceTypeFolder, actionSymlink},
    91  		{"templates", "templates", resourceTypeFolder, actionSymlink},
    92  		{"tests", "tests", resourceTypeFolder, actionSymlink},
    93  		{"fonts", "fonts", resourceTypeFolder, actionSymlink},
    94  		{"utils/policies-roles-mapping.json", "utils/policies-roles-mapping.json", resourceTypeFile, actionSymlink},
    95  	}
    96  
    97  	// Finding resources and setting full path to source to be used for further processing
    98  	for i, testResource := range testResourcesToSetup {
    99  		if testResource.resType == resourceTypeFile {
   100  			srcPath = findFile(testResource.src)
   101  			if srcPath == "" {
   102  				panic(fmt.Sprintf("Failed to find file %s", testResource.src))
   103  			}
   104  
   105  			testResourcesToSetup[i].src = srcPath
   106  		} else if testResource.resType == resourceTypeFolder {
   107  			srcPath, found = findDir(testResource.src)
   108  			if !found {
   109  				panic(fmt.Sprintf("Failed to find folder %s", testResource.src))
   110  			}
   111  
   112  			testResourcesToSetup[i].src = srcPath
   113  		} else {
   114  			panic(fmt.Sprintf("Invalid resource type: %d", testResource.resType))
   115  		}
   116  	}
   117  
   118  	return testResourcesToSetup
   119  }
   120  
   121  func CopyFile(src, dst string) error {
   122  	fileBackend, err := filesstore.NewFileBackend(filesstore.FileBackendSettings{DriverName: "local", Directory: ""})
   123  	if err != nil {
   124  		return errors.Wrapf(err, "failed to copy file %s to %s", src, dst)
   125  	}
   126  	if err = fileBackend.CopyFile(src, dst); err != nil {
   127  		return errors.Wrapf(err, "failed to copy file %s to %s", src, dst)
   128  	}
   129  	return nil
   130  }
   131  
   132  func SetupTestResources() (string, error) {
   133  	testResourcesToSetup := getTestResourcesToSetup()
   134  
   135  	tempDir, err := ioutil.TempDir("", "testlib")
   136  	if err != nil {
   137  		return "", errors.Wrap(err, "failed to create temporary directory")
   138  	}
   139  
   140  	pluginsDir := path.Join(tempDir, "plugins")
   141  	err = os.Mkdir(pluginsDir, 0700)
   142  	if err != nil {
   143  		return "", errors.Wrapf(err, "failed to create plugins directory %s", pluginsDir)
   144  	}
   145  
   146  	clientDir := path.Join(tempDir, "client")
   147  	err = os.Mkdir(clientDir, 0700)
   148  	if err != nil {
   149  		return "", errors.Wrapf(err, "failed to create client directory %s", clientDir)
   150  	}
   151  
   152  	err = setupConfig(path.Join(tempDir, "config"))
   153  	if err != nil {
   154  		return "", errors.Wrap(err, "failed to setup config")
   155  	}
   156  
   157  	var resourceDestInTemp string
   158  
   159  	// Setting up test resources in temp.
   160  	// Action in each resource tells whether it needs to be copied or just symlinked
   161  	for _, testResource := range testResourcesToSetup {
   162  		resourceDestInTemp = filepath.Join(tempDir, testResource.dest)
   163  
   164  		if testResource.action == actionCopy {
   165  			if testResource.resType == resourceTypeFile {
   166  				if err = CopyFile(testResource.src, resourceDestInTemp); err != nil {
   167  					return "", err
   168  				}
   169  			} else if testResource.resType == resourceTypeFolder {
   170  				err = utils.CopyDir(testResource.src, resourceDestInTemp)
   171  				if err != nil {
   172  					return "", errors.Wrapf(err, "failed to copy folder %s to %s", testResource.src, resourceDestInTemp)
   173  				}
   174  			}
   175  		} else if testResource.action == actionSymlink {
   176  			destDir := path.Dir(resourceDestInTemp)
   177  			if destDir != "." {
   178  				err = os.MkdirAll(destDir, os.ModePerm)
   179  				if err != nil {
   180  					return "", errors.Wrapf(err, "failed to make dir %s", destDir)
   181  				}
   182  			}
   183  
   184  			err = os.Symlink(testResource.src, resourceDestInTemp)
   185  			if err != nil {
   186  				return "", errors.Wrapf(err, "failed to symlink %s to %s", testResource.src, resourceDestInTemp)
   187  			}
   188  		} else {
   189  			return "", errors.Wrapf(err, "Invalid action: %d", testResource.action)
   190  		}
   191  
   192  	}
   193  
   194  	return tempDir, nil
   195  }
   196  
   197  func setupConfig(configDir string) error {
   198  	var err error
   199  	var config model.Config
   200  
   201  	config.SetDefaults()
   202  
   203  	err = os.Mkdir(configDir, 0700)
   204  	if err != nil {
   205  		return errors.Wrapf(err, "failed to create config directory %s", configDir)
   206  	}
   207  
   208  	configJSON := path.Join(configDir, "config.json")
   209  	err = ioutil.WriteFile(configJSON, []byte(config.ToJson()), 0644)
   210  	if err != nil {
   211  		return errors.Wrapf(err, "failed to write config to %s", configJSON)
   212  	}
   213  
   214  	return nil
   215  }