11import json
22import os
33import sys
4+ import tempfile
45import unittest
56from collections import OrderedDict
67from shutil import copyfile
@@ -30,6 +31,14 @@ def test_list_configs_when_one(self):
3031 self .assertEqual (1 , len (configs ))
3132 self .assertEqual ('conf_x' , configs [0 ].name )
3233
34+ def test_list_configs_when_one_and_symlink (self ):
35+ conf_path = os .path .join (test_utils .temp_folder , 'runners' , 'sub' , 'x.json' )
36+ with self ._temporary_file_symlink (conf_path , {'name' : 'test X' }):
37+ configs = self .config_service .list_configs (self .user )
38+ self .assertEqual (1 , len (configs ))
39+ self .assertEqual ('test X' , configs [0 ].name )
40+ self .assertEqual ('sub' , configs [0 ].group )
41+
3342 def test_list_configs_when_multiple (self ):
3443 _create_script_config_file ('conf_x' )
3544 _create_script_config_file ('conf_y' )
@@ -40,9 +49,9 @@ def test_list_configs_when_multiple(self):
4049 self .assertCountEqual (['conf_x' , 'conf_y' , 'A B C' ], conf_names )
4150
4251 def test_list_configs_when_multiple_and_subfolders (self ):
43- _create_script_config_file ('conf_x' , subfolder = 's1' )
44- _create_script_config_file ('conf_y' , subfolder = 's2' )
45- _create_script_config_file ('ABC' , subfolder = os .path .join ('s1' , 'inner' ))
52+ _create_script_config_file ('conf_x' , subfolder = 's1' )
53+ _create_script_config_file ('conf_y' , subfolder = 's2' )
54+ _create_script_config_file ('ABC' , subfolder = os .path .join ('s1' , 'inner' ))
4655
4756 configs = self .config_service .list_configs (self .user )
4857 conf_names = [config .name for config in configs ]
@@ -114,6 +123,36 @@ def test_load_config_with_slash_in_name(self):
114123 config = self .config_service .load_config_model ('Name with slash /' , self .user )
115124 self .assertEqual ('Name with slash /' , config .name )
116125
126+ def test_list_configs_when_multiple_subfolders_and_symlink (self ):
127+ def create_config_file (name , relative_path , group = None ):
128+ filename = os .path .basename (relative_path )
129+ test_utils .write_script_config (
130+ {'name' : name , 'group' : group },
131+ filename ,
132+ config_folder = os .path .join (test_utils .temp_folder , 'runners' , os .path .dirname (relative_path )))
133+
134+ subfolder = os .path .join (test_utils .temp_folder , 'runners' , 'sub' )
135+ symlink_path = os .path .join (subfolder , 'x.json' )
136+ with self ._temporary_file_symlink (symlink_path , {'name' : 'test X' }):
137+ create_config_file ('conf Y' , os .path .join ('sub' , 'y' , 'conf_y.json' ))
138+ create_config_file ('conf Z' , os .path .join ('sub' , 'z' , 'conf_z.json' ))
139+ create_config_file ('conf A' , 'conf_a.json' )
140+ create_config_file ('conf B' , os .path .join ('b' , 'conf_b.json' ))
141+ create_config_file ('conf C' , os .path .join ('c' , 'conf_c.json' ), group = 'test group' )
142+
143+ configs = self .config_service .list_configs (self .user )
144+ actual_name_group_map = {c .name : c .group for c in configs }
145+
146+ self .assertEqual (
147+ actual_name_group_map ,
148+ {'test X' : 'sub' ,
149+ 'conf Y' : 'sub' ,
150+ 'conf Z' : 'sub' ,
151+ 'conf A' : None ,
152+ 'conf B' : 'b' ,
153+ 'conf C' : 'test group' },
154+ )
155+
117156 def tearDown (self ):
118157 super ().tearDown ()
119158 test_utils .cleanup ()
@@ -125,7 +164,19 @@ def setUp(self):
125164 self .user = User ('ConfigServiceTest' , {AUTH_USERNAME : 'ConfigServiceTest' })
126165 self .admin_user = User ('admin_user' , {AUTH_USERNAME : 'The Admin' })
127166 authorizer = Authorizer (ANY_USER , ['admin_user' ], [], [], EmptyGroupProvider ())
128- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
167+ self .config_service = ConfigService (authorizer , test_utils .temp_folder , True , test_utils .process_invoker )
168+
169+ @staticmethod
170+ def _temporary_file_symlink (symlink_path , file_content : dict ):
171+ f = tempfile .NamedTemporaryFile ()
172+
173+ f .write (json .dumps (file_content ).encode ('utf-8' ))
174+ f .flush ()
175+ subdir = os .path .dirname (symlink_path )
176+ os .makedirs (subdir )
177+ os .symlink (f .name , symlink_path )
178+
179+ return f
129180
130181
131182class ConfigServiceAuthTest (unittest .TestCase ):
@@ -209,7 +260,11 @@ def setUp(self):
209260 authorizer = Authorizer ([], ['adm_user' ], [], [], EmptyGroupProvider ())
210261 self .user1 = User ('user1' , {})
211262 self .admin_user = User ('adm_user' , {})
212- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
263+ self .config_service = ConfigService (
264+ authorizer ,
265+ test_utils .temp_folder ,
266+ True ,
267+ test_utils .process_invoker )
213268
214269
215270def script_path (path ):
@@ -242,7 +297,7 @@ def setUp(self):
242297
243298 authorizer = Authorizer ([], ['admin_user' , 'admin_non_editor' ], [], ['admin_user' ], EmptyGroupProvider ())
244299 self .admin_user = User ('admin_user' , {})
245- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
300+ self .config_service = ConfigService (authorizer , test_utils .temp_folder , True , test_utils .process_invoker )
246301
247302 def tearDown (self ):
248303 super ().tearDown ()
@@ -416,7 +471,7 @@ def setUp(self):
416471
417472 authorizer = Authorizer ([], ['admin_user' , 'admin_non_editor' ], [], ['admin_user' ], EmptyGroupProvider ())
418473 self .admin_user = User ('admin_user' , {})
419- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
474+ self .config_service = ConfigService (authorizer , test_utils .temp_folder , True , test_utils .process_invoker )
420475
421476 for suffix in 'XYZ' :
422477 name = 'Conf ' + suffix
@@ -669,7 +724,7 @@ def setUp(self):
669724
670725 authorizer = Authorizer ([], ['admin_user' ], [], [], EmptyGroupProvider ())
671726 self .admin_user = User ('admin_user' , {})
672- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
727+ self .config_service = ConfigService (authorizer , test_utils .temp_folder , True , test_utils .process_invoker )
673728
674729 def tearDown (self ):
675730 super ().tearDown ()
@@ -717,7 +772,7 @@ def setUp(self) -> None:
717772
718773 authorizer = Authorizer ([], ['admin_user' , 'admin_non_editor' ], [], ['admin_user' ], EmptyGroupProvider ())
719774 self .admin_user = User ('admin_user' , {})
720- self .config_service = ConfigService (authorizer , test_utils .temp_folder , test_utils .process_invoker )
775+ self .config_service = ConfigService (authorizer , test_utils .temp_folder , True , test_utils .process_invoker )
721776
722777 for pair in [('script.py' , b'123' ),
723778 ('another.py' , b'xyz' ),
0 commit comments