1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
14 "git.arvados.org/arvados.git/sdk/go/arvados"
18 // Gocheck boilerplate
19 func Test(t *testing.T) {
23 type TestSuite struct {
26 users map[string]arvados.User
29 func (s *TestSuite) SetUpTest(c *C) {
30 s.ac = arvados.NewClientFromEnv()
31 u, err := s.ac.CurrentUser()
33 c.Assert(u.IsAdmin, Equals, true)
35 s.users = make(map[string]arvados.User)
36 ul := arvados.UserList{}
37 s.ac.RequestAndDecode(&ul, "GET", "/arvados/v1/users", nil, arvados.ResourceListParams{})
38 c.Assert(ul.ItemsAvailable, Not(Equals), 0)
39 s.users = make(map[string]arvados.User)
40 for _, u := range ul.Items {
44 // Set up command config
45 os.Args = []string{"cmd", "somefile.csv"}
46 config, err := GetConfig()
51 func (s *TestSuite) TearDownTest(c *C) {
53 // Reset database to fixture state after every test run.
54 err := s.cfg.Client.RequestAndDecode(&dst, "POST", "/database/reset", nil, nil)
58 var _ = Suite(&TestSuite{})
60 // MakeTempCSVFile creates a temp file with data as comma separated values
61 func MakeTempCSVFile(data [][]string) (f *os.File, err error) {
62 f, err = ioutil.TempFile("", "test_sync_users")
66 for _, line := range data {
67 fmt.Fprintf(f, "%s\n", strings.Join(line, ","))
73 func ListUsers(ac *arvados.Client) ([]arvados.User, error) {
74 var ul arvados.UserList
75 err := ac.RequestAndDecode(&ul, "GET", "/arvados/v1/users", nil, arvados.ResourceListParams{})
82 func (s *TestSuite) TestParseFlagsWithoutPositionalArgument(c *C) {
83 os.Args = []string{"cmd", "-verbose"}
84 err := ParseFlags(&ConfigParams{})
88 func (s *TestSuite) TestParseFlagsWithPositionalArgument(c *C) {
90 os.Args = []string{"cmd", "/tmp/somefile.csv"}
91 err := ParseFlags(&cfg)
93 c.Assert(cfg.Path, Equals, "/tmp/somefile.csv")
94 c.Assert(cfg.Verbose, Equals, false)
95 c.Assert(cfg.DeactivateUnlisted, Equals, false)
98 func (s *TestSuite) TestParseFlagsWithOptionalFlags(c *C) {
100 os.Args = []string{"cmd", "-verbose", "-deactivate-unlisted", "/tmp/somefile.csv"}
101 err := ParseFlags(&cfg)
103 c.Assert(cfg.Path, Equals, "/tmp/somefile.csv")
104 c.Assert(cfg.Verbose, Equals, true)
105 c.Assert(cfg.DeactivateUnlisted, Equals, true)
108 func (s *TestSuite) TestGetConfig(c *C) {
109 os.Args = []string{"cmd", "/tmp/somefile.csv"}
110 cfg, err := GetConfig()
112 c.Assert(cfg.AnonUserUUID, Not(Equals), "")
113 c.Assert(cfg.SysUserUUID, Not(Equals), "")
114 c.Assert(cfg.CurrentUser, Not(Equals), "")
115 c.Assert(cfg.ClusterID, Not(Equals), "")
116 c.Assert(cfg.Client, NotNil)
119 func (s *TestSuite) TestFailOnEmptyFields(c *C) {
120 records := [][]string{
121 {"", "first-name", "last-name", "1", "0"},
122 {"user@example", "", "last-name", "1", "0"},
123 {"user@example", "first-name", "", "1", "0"},
124 {"user@example", "first-name", "last-name", "", "0"},
125 {"user@example", "first-name", "last-name", "1", ""},
127 for _, record := range records {
128 data := [][]string{record}
129 tmpfile, err := MakeTempCSVFile(data)
131 defer os.Remove(tmpfile.Name())
132 s.cfg.Path = tmpfile.Name()
134 c.Assert(err, NotNil)
135 c.Assert(err, ErrorMatches, ".*fields cannot be empty.*")
139 func (s *TestSuite) TestIgnoreSpaces(c *C) {
140 // Make sure users aren't already there from fixtures
141 for _, user := range s.users {
143 found := e == "user1@example.com" || e == "user2@example.com" || e == "user3@example.com"
144 c.Assert(found, Equals, false)
146 // Use CSV data with leading/trailing whitespaces, confirm that they get ignored
148 {" user1@example.com", " Example", " User1", "1", "0"},
149 {"user2@example.com ", "Example ", "User2 ", "1", "0"},
150 {" user3@example.com ", " Example ", " User3 ", "1", "0"},
152 tmpfile, err := MakeTempCSVFile(data)
154 defer os.Remove(tmpfile.Name())
155 s.cfg.Path = tmpfile.Name()
158 users, err := ListUsers(s.cfg.Client)
160 for _, userNr := range []int{1, 2, 3} {
162 for _, user := range users {
163 if user.Email == fmt.Sprintf("user%d@example.com", userNr) &&
164 user.LastName == fmt.Sprintf("User%d", userNr) &&
165 user.FirstName == "Example" && user.IsActive == true {
170 c.Assert(found, Equals, true)
174 // Error out when records have != 5 records
175 func (s *TestSuite) TestWrongNumberOfFields(c *C) {
176 for _, testCase := range [][][]string{
177 {{"user1@example.com", "Example", "User1", "1"}},
178 {{"user1@example.com", "Example", "User1", "1", "0", "extra data"}},
180 tmpfile, err := MakeTempCSVFile(testCase)
182 defer os.Remove(tmpfile.Name())
183 s.cfg.Path = tmpfile.Name()
185 c.Assert(err, NotNil)
186 c.Assert(err, ErrorMatches, ".*expected 5 fields, found.*")
190 // Error out when records have incorrect data types
191 func (s *TestSuite) TestWrongDataFields(c *C) {
192 for _, testCase := range [][][]string{
193 {{"user1@example.com", "Example", "User1", "yep", "0"}},
194 {{"user1@example.com", "Example", "User1", "1", "nope"}},
196 tmpfile, err := MakeTempCSVFile(testCase)
198 defer os.Remove(tmpfile.Name())
199 s.cfg.Path = tmpfile.Name()
201 c.Assert(err, NotNil)
202 c.Assert(err, ErrorMatches, ".*parsing error at line.*[active|admin] status not recognized.*")
206 // Activate and deactivate users
207 func (s *TestSuite) TestUserCreationAndUpdate(c *C) {
208 testCases := []struct {
215 Email: "user1@example.com",
216 FirstName: "Example",
221 Email: "admin1@example.com",
222 FirstName: "Example",
227 // Make sure users aren't already there from fixtures
228 for _, user := range s.users {
230 found := e == testCases[0].Email || e == testCases[1].Email
231 c.Assert(found, Equals, false)
235 {testCases[0].Email, testCases[0].FirstName, testCases[0].LastName, fmt.Sprintf("%t", testCases[0].Active), fmt.Sprintf("%t", testCases[0].Admin)},
236 {testCases[1].Email, testCases[1].FirstName, testCases[1].LastName, fmt.Sprintf("%t", testCases[1].Active), fmt.Sprintf("%t", testCases[1].Admin)},
238 tmpfile, err := MakeTempCSVFile(data)
240 defer os.Remove(tmpfile.Name())
241 s.cfg.Path = tmpfile.Name()
245 users, err := ListUsers(s.cfg.Client)
247 for _, tc := range testCases {
248 var foundUser arvados.User
249 for _, user := range users {
250 if user.Email == tc.Email {
255 c.Assert(foundUser, NotNil)
256 c.Logf("Checking recently created user %q", foundUser.Email)
257 c.Assert(foundUser.FirstName, Equals, tc.FirstName)
258 c.Assert(foundUser.LastName, Equals, tc.LastName)
259 c.Assert(foundUser.IsActive, Equals, true)
260 c.Assert(foundUser.IsAdmin, Equals, tc.Admin)
263 testCases[0].Active = false
264 testCases[1].Active = false
266 {testCases[0].Email, testCases[0].FirstName, testCases[0].LastName, fmt.Sprintf("%t", testCases[0].Active), fmt.Sprintf("%t", testCases[0].Admin)},
267 {testCases[1].Email, testCases[1].FirstName, testCases[1].LastName, fmt.Sprintf("%t", testCases[1].Active), fmt.Sprintf("%t", testCases[1].Admin)},
269 tmpfile, err = MakeTempCSVFile(data)
271 defer os.Remove(tmpfile.Name())
272 s.cfg.Path = tmpfile.Name()
276 users, err = ListUsers(s.cfg.Client)
278 for _, tc := range testCases {
279 var foundUser arvados.User
280 for _, user := range users {
281 if user.Email == tc.Email {
286 c.Assert(foundUser, NotNil)
287 c.Logf("Checking recently deactivated user %q", foundUser.Email)
288 c.Assert(foundUser.FirstName, Equals, tc.FirstName)
289 c.Assert(foundUser.LastName, Equals, tc.LastName)
290 c.Assert(foundUser.IsActive, Equals, false)
291 c.Assert(foundUser.IsAdmin, Equals, false) // inactive users cannot be admins