github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/seafile/seafile_internal_test.go (about)

     1  package seafile
     2  
     3  import (
     4  	"context"
     5  	"path"
     6  	"testing"
     7  
     8  	"github.com/rclone/rclone/fs"
     9  	"github.com/rclone/rclone/fs/config/configmap"
    10  	"github.com/rclone/rclone/fs/config/obscure"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  type pathData struct {
    16  	configLibrary   string // Library specified in the config
    17  	configRoot      string // Root directory specified in the config
    18  	argumentPath    string // Path given as an argument in the command line
    19  	expectedLibrary string
    20  	expectedPath    string
    21  }
    22  
    23  // Test the method to split a library name and a path
    24  // from a mix of configuration data and path command line argument
    25  func TestSplitPath(t *testing.T) {
    26  	testData := []pathData{
    27  		{
    28  			configLibrary:   "",
    29  			configRoot:      "",
    30  			argumentPath:    "",
    31  			expectedLibrary: "",
    32  			expectedPath:    "",
    33  		},
    34  		{
    35  			configLibrary:   "",
    36  			configRoot:      "",
    37  			argumentPath:    "Library",
    38  			expectedLibrary: "Library",
    39  			expectedPath:    "",
    40  		},
    41  		{
    42  			configLibrary:   "",
    43  			configRoot:      "",
    44  			argumentPath:    path.Join("Library", "path", "to", "file"),
    45  			expectedLibrary: "Library",
    46  			expectedPath:    path.Join("path", "to", "file"),
    47  		},
    48  		{
    49  			configLibrary:   "Library",
    50  			configRoot:      "",
    51  			argumentPath:    "",
    52  			expectedLibrary: "Library",
    53  			expectedPath:    "",
    54  		},
    55  		{
    56  			configLibrary:   "Library",
    57  			configRoot:      "",
    58  			argumentPath:    "path",
    59  			expectedLibrary: "Library",
    60  			expectedPath:    "path",
    61  		},
    62  		{
    63  			configLibrary:   "Library",
    64  			configRoot:      "",
    65  			argumentPath:    path.Join("path", "to", "file"),
    66  			expectedLibrary: "Library",
    67  			expectedPath:    path.Join("path", "to", "file"),
    68  		},
    69  		{
    70  			configLibrary:   "Library",
    71  			configRoot:      "root",
    72  			argumentPath:    "",
    73  			expectedLibrary: "Library",
    74  			expectedPath:    "root",
    75  		},
    76  		{
    77  			configLibrary:   "Library",
    78  			configRoot:      path.Join("root", "path"),
    79  			argumentPath:    "",
    80  			expectedLibrary: "Library",
    81  			expectedPath:    path.Join("root", "path"),
    82  		},
    83  		{
    84  			configLibrary:   "Library",
    85  			configRoot:      "root",
    86  			argumentPath:    "path",
    87  			expectedLibrary: "Library",
    88  			expectedPath:    path.Join("root", "path"),
    89  		},
    90  		{
    91  			configLibrary:   "Library",
    92  			configRoot:      "root",
    93  			argumentPath:    path.Join("path", "to", "file"),
    94  			expectedLibrary: "Library",
    95  			expectedPath:    path.Join("root", "path", "to", "file"),
    96  		},
    97  		{
    98  			configLibrary:   "Library",
    99  			configRoot:      path.Join("root", "path"),
   100  			argumentPath:    path.Join("subpath", "to", "file"),
   101  			expectedLibrary: "Library",
   102  			expectedPath:    path.Join("root", "path", "subpath", "to", "file"),
   103  		},
   104  	}
   105  	for _, test := range testData {
   106  		fs := &Fs{
   107  			libraryName:   test.configLibrary,
   108  			rootDirectory: test.configRoot,
   109  		}
   110  		libraryName, path := fs.splitPath(test.argumentPath)
   111  
   112  		assert.Equal(t, test.expectedLibrary, libraryName)
   113  		assert.Equal(t, test.expectedPath, path)
   114  	}
   115  }
   116  
   117  func TestSplitPathIntoSlice(t *testing.T) {
   118  	testData := map[string][]string{
   119  		"1":     {"1"},
   120  		"/1":    {"1"},
   121  		"/1/":   {"1"},
   122  		"1/2/3": {"1", "2", "3"},
   123  	}
   124  	for input, expected := range testData {
   125  		output := splitPath(input)
   126  		assert.Equal(t, expected, output)
   127  	}
   128  }
   129  
   130  func Test2FAStateMachine(t *testing.T) {
   131  	fixtures := []struct {
   132  		name               string
   133  		mapper             configmap.Mapper
   134  		input              fs.ConfigIn
   135  		expectState        string
   136  		expectErrorMessage string
   137  		expectResult       string
   138  		expectFail         bool
   139  		expectNil          bool
   140  	}{
   141  		{
   142  			name:       "no url",
   143  			mapper:     configmap.Simple{},
   144  			input:      fs.ConfigIn{State: ""},
   145  			expectFail: true,
   146  		},
   147  		{
   148  			name:       "unknown state",
   149  			mapper:     configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   150  			input:      fs.ConfigIn{State: "unknown"},
   151  			expectFail: true,
   152  		},
   153  		{
   154  			name:      "2fa not set",
   155  			mapper:    configmap.Simple{"url": "http://localhost/"},
   156  			input:     fs.ConfigIn{State: ""},
   157  			expectNil: true,
   158  		},
   159  		{
   160  			name:        "no password in config",
   161  			mapper:      configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   162  			input:       fs.ConfigIn{State: ""},
   163  			expectState: "password",
   164  		},
   165  		{
   166  			name:        "config ready for 2fa token",
   167  			mapper:      configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username", "pass": obscure.MustObscure("password")},
   168  			input:       fs.ConfigIn{State: ""},
   169  			expectState: "2fa",
   170  		},
   171  		{
   172  			name:               "password not entered",
   173  			mapper:             configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   174  			input:              fs.ConfigIn{State: "password"},
   175  			expectState:        "",
   176  			expectErrorMessage: "Password can't be blank",
   177  		},
   178  		{
   179  			name:        "password entered",
   180  			mapper:      configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   181  			input:       fs.ConfigIn{State: "password", Result: "password"},
   182  			expectState: "2fa",
   183  		},
   184  		{
   185  			name:        "ask for a 2fa code",
   186  			mapper:      configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   187  			input:       fs.ConfigIn{State: "2fa"},
   188  			expectState: "2fa_do",
   189  		},
   190  		{
   191  			name:               "no 2fa code entered",
   192  			mapper:             configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   193  			input:              fs.ConfigIn{State: "2fa_do"},
   194  			expectState:        "2fa", // ask for a code again
   195  			expectErrorMessage: "2FA codes can't be blank",
   196  		},
   197  		{
   198  			name:        "2fa error and retry",
   199  			mapper:      configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   200  			input:       fs.ConfigIn{State: "2fa_error", Result: "true"},
   201  			expectState: "2fa", // ask for a code again
   202  		},
   203  		{
   204  			name:       "2fa error and fail",
   205  			mapper:     configmap.Simple{"url": "http://localhost/", "2fa": "true", "user": "username"},
   206  			input:      fs.ConfigIn{State: "2fa_error"},
   207  			expectFail: true,
   208  		},
   209  	}
   210  
   211  	for _, fixture := range fixtures {
   212  		t.Run(fixture.name, func(t *testing.T) {
   213  			output, err := Config(context.Background(), "test", fixture.mapper, fixture.input)
   214  			if fixture.expectFail {
   215  				require.Error(t, err)
   216  				t.Log(err)
   217  				return
   218  			}
   219  			if fixture.expectNil {
   220  				require.Nil(t, output)
   221  				return
   222  			}
   223  			assert.Equal(t, fixture.expectState, output.State)
   224  			assert.Equal(t, fixture.expectErrorMessage, output.Error)
   225  			assert.Equal(t, fixture.expectResult, output.Result)
   226  		})
   227  	}
   228  }