@@ -174,51 +174,36 @@ def test_backup_via_unprivileged_user(self):
174174class AuthTest (unittest .TestCase ):
175175 pb = None
176176 node = None
177+ test_path = None
177178
178- # TODO move to object scope, replace module_name
179- @classmethod
180- def setUpClass (cls ):
179+ @unittest .skipIf (skip_test , "Module pexpect isn't installed. You need to install it." )
180+ def setUp (self ):
181181
182- super (AuthTest , cls ). setUpClass ()
182+ super (). setUp ()
183183
184- cls .pb = ProbackupTest ()
185- cls .backup_dir = os .path .join (cls .pb .tmp_path , module_name , 'backup' )
184+ self .pb = ProbackupTest ()
185+ self .test_path = os .path .join (self .pb .tmp_path , module_name , self ._testMethodName )
186+ self .backup_dir = os .path .join (self .test_path , 'backup' )
186187
187- cls .node = cls .pb .make_simple_node (
188- base_dir = "{}/node" . format ( module_name ),
188+ self .node = self .pb .make_simple_node (
189+ base_dir = os . path . join ( self . test_path , 'node' ),
189190 set_replication = True ,
190191 initdb_params = ['--data-checksums' , '--auth-host=md5' ]
191192 )
192193
193- cls . username = cls .pb .get_username ()
194+ self . modify_pg_hba ( self . node , self .pb .get_username () )
194195
195- cls .modify_pg_hba (cls .node )
196-
197- cls .pb .init_pb (cls .backup_dir )
198- cls .pb .add_instance (cls .backup_dir , cls .node .name , cls .node )
199- cls .pb .set_archiving (cls .backup_dir , cls .node .name , cls .node )
196+ self .pb .init_pb (self .backup_dir )
197+ self .pb .add_instance (self .backup_dir , self .node .name , self .node )
198+ self .pb .set_archiving (self .backup_dir , self .node .name , self .node )
200199 try :
201- cls .node .slow_start ()
200+ self .node .slow_start ()
202201 except StartNodeException :
203202 raise unittest .skip ("Node hasn't started" )
204203
205- if cls .pb .get_version (cls .node ) < 100000 :
206- cls .node .safe_psql (
207- "postgres" ,
208- "CREATE ROLE backup WITH LOGIN PASSWORD 'password'; "
209- "GRANT USAGE ON SCHEMA pg_catalog TO backup; "
210- "GRANT EXECUTE ON FUNCTION current_setting(text) TO backup; "
211- "GRANT EXECUTE ON FUNCTION pg_is_in_recovery() TO backup; "
212- "GRANT EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) TO backup; "
213- "GRANT EXECUTE ON FUNCTION pg_stop_backup() TO backup; "
214- "GRANT EXECUTE ON FUNCTION pg_stop_backup(boolean) TO backup; "
215- "GRANT EXECUTE ON FUNCTION pg_create_restore_point(text) TO backup; "
216- "GRANT EXECUTE ON FUNCTION pg_switch_xlog() TO backup; "
217- "GRANT EXECUTE ON FUNCTION txid_current() TO backup; "
218- "GRANT EXECUTE ON FUNCTION txid_current_snapshot() TO backup; "
219- "GRANT EXECUTE ON FUNCTION txid_snapshot_xmax(txid_snapshot) TO backup;" )
220- elif cls .pb .get_version (cls .node ) < 150000 :
221- cls .node .safe_psql (
204+ version = self .pb .get_version (self .node )
205+ if version < 150000 :
206+ self .node .safe_psql (
222207 "postgres" ,
223208 "CREATE ROLE backup WITH LOGIN PASSWORD 'password'; "
224209 "GRANT USAGE ON SCHEMA pg_catalog TO backup; "
@@ -233,7 +218,7 @@ def setUpClass(cls):
233218 "GRANT EXECUTE ON FUNCTION txid_current_snapshot() TO backup; "
234219 "GRANT EXECUTE ON FUNCTION txid_snapshot_xmax(txid_snapshot) TO backup;" )
235220 else :
236- cls .node .safe_psql (
221+ self .node .safe_psql (
237222 "postgres" ,
238223 "CREATE ROLE backup WITH LOGIN PASSWORD 'password'; "
239224 "GRANT USAGE ON SCHEMA pg_catalog TO backup; "
@@ -247,16 +232,29 @@ def setUpClass(cls):
247232 "GRANT EXECUTE ON FUNCTION txid_current_snapshot() TO backup; "
248233 "GRANT EXECUTE ON FUNCTION txid_snapshot_xmax(txid_snapshot) TO backup;" )
249234
250- cls .pgpass_file = os .path .join (os .path .expanduser ('~' ), '.pgpass' )
251-
252- # TODO move to object scope, replace module_name
253- @classmethod
254- def tearDownClass (cls ):
255- cls .node .cleanup ()
256- cls .pb .del_test_dir (module_name , '' )
235+ if version >= 150000 :
236+ home_dir = os .path .join (self .test_path , "home" )
237+ os .makedirs (home_dir , exist_ok = True )
238+ self .pb .test_env ['HOME' ] = home_dir
239+ self .pgpass_file = os .path .join (home_dir , '.pgpass' )
240+ self .pgpass_file_lock = None
241+ else :
242+ # before PGv15 only true home dir were inspected.
243+ # Since we can't have separate file per test, we have to serialize
244+ # tests.
245+ self .pgpass_file = os .path .join (os .path .expanduser ('~' ), '.pgpass' )
246+ self .pgpass_file_lock = self .pgpass_file + '~probackup_test_lock'
247+ # have to lock pgpass by creating file in exclusive mode
248+ for i in range (120 ):
249+ try :
250+ open (self .pgpass_file_lock , "x" ).close ()
251+ except FileExistsError :
252+ time .sleep (1 )
253+ else :
254+ break
255+ else :
256+ raise TimeoutError ("can't create ~/.pgpass~probackup_test_lock for 120 seconds" )
257257
258- @unittest .skipIf (skip_test , "Module pexpect isn't installed. You need to install it." )
259- def setUp (self ):
260258 self .pb_cmd = ['backup' ,
261259 '-B' , self .backup_dir ,
262260 '--instance' , self .node .name ,
@@ -268,6 +266,19 @@ def setUp(self):
268266 ]
269267
270268 def tearDown (self ):
269+ if (self .pgpass_file_lock
270+ and hasattr (self , "pgpass_line" )
271+ and os .path .exists (self .pgpass_file )):
272+ with open (self .pgpass_file , 'r' , encoding = "utf-8" ) as fl :
273+ lines = fl .readlines ()
274+ if self .pgpass_line in lines :
275+ lines .remove (self .pgpass_line )
276+ if len (lines ) == 0 :
277+ os .remove (self .pgpass_file )
278+ else :
279+ with open (self .pgpass_file , 'w' , encoding = "utf-8" ) as fl :
280+ fl .writelines (lines )
281+
271282 if "PGPASSWORD" in self .pb .test_env .keys ():
272283 del self .pb .test_env ["PGPASSWORD" ]
273284
@@ -279,6 +290,10 @@ def tearDown(self):
279290 except OSError :
280291 pass
281292
293+ test_path = os .path .join (self .pb .tmp_path , module_name )
294+ self .node .cleanup ()
295+ self .pb .del_test_dir (test_path , self ._testMethodName )
296+
282297 def test_empty_password (self ):
283298 """ Test case: PGPB_AUTH03 - zero password length """
284299 try :
@@ -313,7 +328,7 @@ def test_ctrl_c_event(self):
313328
314329 def test_pgpassfile_env (self ):
315330 """ Test case: PGPB_AUTH06 - set environment var PGPASSFILE """
316- path = os .path .join (self .pb . tmp_path , module_name , 'pgpass.conf' )
331+ path = os .path .join (self .test_path , 'pgpass.conf' )
317332 line = ":" .join (['127.0.0.1' , str (self .node .port ), 'postgres' , 'backup' , 'password' ])
318333 self .create_pgpass (path , line )
319334 self .pb .test_env ["PGPASSFILE" ] = path
@@ -367,7 +382,7 @@ def run_pb_with_auth(self, password=None, add_args = [], kill=False):
367382
368383
369384 @classmethod
370- def modify_pg_hba (cls , node ):
385+ def modify_pg_hba (self , node , username ):
371386 """
372387 Description:
373388 Add trust authentication for user postgres. Need for add new role and set grant.
@@ -378,11 +393,12 @@ def modify_pg_hba(cls, node):
378393 with open (hba_conf , 'r+' ) as fio :
379394 data = fio .read ()
380395 fio .seek (0 )
381- fio .write ('host\t all\t %s\t 127.0.0.1/0\t trust\n %s' % (cls . username , data ))
396+ fio .write ('host\t all\t %s\t 127.0.0.1/0\t trust\n %s' % (username , data ))
382397
383398
384399 def create_pgpass (self , path , line ):
400+ self .pgpass_line = line + "\n "
385401 with open (path , 'w' ) as passfile :
386402 # host:port:db:username:password
387- passfile .write (line )
403+ passfile .write (self . pgpass_line )
388404 os .chmod (path , 0o600 )
0 commit comments