5454oauth_token = STUV
5555"""
5656
57+ ssl_verify_str_config = """[global]
58+ default = one
59+ ssl_verify = /etc/ssl/certs/ca-certificates.crt
60+
61+ [one]
62+ url = http://one.url
63+ private_token = ABCDEF
64+ """
65+
5766custom_user_agent_config = f"""[global]
5867default = one
5968user_agent ={ custom_user_agent }
6978private_token = ABCDEF
7079"""
7180
72- missing_attr_config = """[global]
81+ invalid_data_config = """[global]
7382[one]
7483url = http://one.url
7584
8392url = http://four.url
8493private_token = ABCDEF
8594per_page = 200
95+
96+ [invalid-api-version]
97+ url = http://invalid-api-version.url
98+ private_token = ABCDEF
99+ api_version = 1
86100"""
87101
88102
@@ -173,7 +187,7 @@ def test_invalid_id(m_open, mock_clean_env, monkeypatch):
173187
174188@mock .patch ("builtins.open" )
175189def test_invalid_data (m_open ,monkeypatch ):
176- fd = io .StringIO (missing_attr_config )
190+ fd = io .StringIO (invalid_data_config )
177191fd .close = mock .Mock (return_value = None ,side_effect = lambda :fd .seek (0 ))
178192m_open .return_value = fd
179193
@@ -185,9 +199,14 @@ def test_invalid_data(m_open, monkeypatch):
185199config .GitlabConfigParser (gitlab_id = "two" )
186200with pytest .raises (config .GitlabDataError ):
187201config .GitlabConfigParser (gitlab_id = "three" )
188- with pytest .raises (config .GitlabDataError )as emgr :
202+
203+ with pytest .raises (config .GitlabDataError )as e :
189204config .GitlabConfigParser ("four" )
190- assert "Unsupported per_page number: 200" == emgr .value .args [0 ]
205+ assert str (e .value )== "Unsupported per_page number: 200"
206+
207+ with pytest .raises (config .GitlabDataError )as e :
208+ config .GitlabConfigParser ("invalid-api-version" )
209+ assert str (e .value )== "Unsupported API version: 1"
191210
192211
193212@mock .patch ("builtins.open" )
@@ -248,6 +267,18 @@ def test_valid_data(m_open, monkeypatch):
248267assert cp .ssl_verify is True
249268
250269
270+ @mock .patch ("builtins.open" )
271+ def test_ssl_verify_as_str (m_open ,monkeypatch ):
272+ fd = io .StringIO (ssl_verify_str_config )
273+ fd .close = mock .Mock (return_value = None )
274+ m_open .return_value = fd
275+
276+ with monkeypatch .context ()as m :
277+ m .setattr (Path ,"resolve" ,_mock_existent_file )
278+ cp = config .GitlabConfigParser ()
279+ assert cp .ssl_verify == "/etc/ssl/certs/ca-certificates.crt"
280+
281+
251282@mock .patch ("builtins.open" )
252283@pytest .mark .skipif (sys .platform .startswith ("win" ),reason = "Not supported on Windows" )
253284def test_data_from_helper (m_open ,monkeypatch ,tmp_path ):
@@ -286,6 +317,33 @@ def test_data_from_helper(m_open, monkeypatch, tmp_path):
286317assert "secret" == cp .oauth_token
287318
288319
320+ @mock .patch ("builtins.open" )
321+ @pytest .mark .skipif (sys .platform .startswith ("win" ),reason = "Not supported on Windows" )
322+ def test_from_helper_subprocess_error_raises_error (m_open ,monkeypatch ):
323+ # using /usr/bin/false here to force a non-zero return code
324+ fd = io .StringIO (
325+ dedent (
326+ """\
327+ [global]
328+ default = helper
329+
330+ [helper]
331+ url = https://helper.url
332+ oauth_token = helper: /usr/bin/false
333+ """
334+ )
335+ )
336+
337+ fd .close = mock .Mock (return_value = None )
338+ m_open .return_value = fd
339+ with monkeypatch .context ()as m :
340+ m .setattr (Path ,"resolve" ,_mock_existent_file )
341+ with pytest .raises (config .GitlabConfigHelperError )as e :
342+ config .GitlabConfigParser (gitlab_id = "helper" )
343+
344+ assert "Failed to read oauth_token value from helper" in str (e .value )
345+
346+
289347@mock .patch ("builtins.open" )
290348@pytest .mark .parametrize (
291349"config_string,expected_agent" ,