Skip to content

Commit 7ecae58

Browse files
committed
Add tests for gitlab importer
Signed-off-by: Tushar Goel <[email protected]>
1 parent e33e85a commit 7ecae58

File tree

3 files changed

+169
-166
lines changed

3 files changed

+169
-166
lines changed

vulnerabilities/pipelines/v2_importers/gitlab_importer.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ def steps(cls):
5454
)
5555

5656
purl_type_by_gitlab_scheme = {
57-
# "conan": "conan",
58-
# "gem": "gem",
57+
"conan": "conan",
58+
"gem": "gem",
5959
# Entering issue to parse go package names https://github.com/nexB/vulnerablecode/issues/742
6060
# "go": "golang",
61-
# "maven": "maven",
62-
# "npm": "npm",
63-
# "nuget": "nuget",
61+
"maven": "maven",
62+
"npm": "npm",
63+
"nuget": "nuget",
6464
"packagist": "composer",
65-
# "pypi": "pypi",
65+
"pypi": "pypi",
6666
}
6767

6868
gitlab_scheme_by_purl_type = {v: k for k, v in purl_type_by_gitlab_scheme.items()}
@@ -94,14 +94,23 @@ def collect_advisories(self) -> Iterable[AdvisoryData]:
9494
)
9595
continue
9696

97-
yield parse_gitlab_advisory(
97+
advisory = parse_gitlab_advisory(
9898
file=file_path,
9999
base_path=base_path,
100100
gitlab_scheme_by_purl_type=self.gitlab_scheme_by_purl_type,
101101
purl_type_by_gitlab_scheme=self.purl_type_by_gitlab_scheme,
102102
logger=self.log,
103103
)
104104

105+
if not advisory:
106+
self.log(
107+
f"Failed to parse advisory from {file_path!r}",
108+
level=logging.ERROR,
109+
)
110+
continue
111+
112+
yield advisory
113+
105114
def clean_downloads(self):
106115
if self.vcs_response:
107116
self.log(f"Removing cloned repository")

vulnerabilities/pipelines/v2_importers/ruby_importer.py

Lines changed: 0 additions & 159 deletions
This file was deleted.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
#
7+
8+
from pathlib import Path
9+
from unittest.mock import MagicMock
10+
from unittest.mock import patch
11+
12+
import pytest
13+
14+
from vulnerabilities.importer import AdvisoryData
15+
16+
17+
@pytest.fixture
18+
def mock_vcs_response(tmp_path):
19+
mock_response = MagicMock()
20+
mock_response.dest_dir = str(tmp_path)
21+
mock_response.delete = MagicMock()
22+
return mock_response
23+
24+
25+
@pytest.fixture
26+
def mock_fetch_via_vcs(mock_vcs_response):
27+
with patch("vulnerabilities.pipelines.v2_importers.gitlab_importer.fetch_via_vcs") as mock:
28+
mock.return_value = mock_vcs_response
29+
yield mock
30+
31+
32+
@pytest.fixture
33+
def mock_gitlab_yaml(tmp_path):
34+
advisory_dir = tmp_path / "pypi" / "package_name"
35+
advisory_dir.mkdir(parents=True)
36+
37+
advisory_file = advisory_dir / "CVE-2022-0001.yml"
38+
advisory_file.write_text(
39+
"""
40+
identifier: "CVE-2022-0001"
41+
package_slug: "pypi/package_name"
42+
title: "Example vulnerability"
43+
description: "Example description"
44+
pubdate: "2022-06-15"
45+
affected_range: "<2.0.0"
46+
fixed_versions:
47+
- "2.0.0"
48+
urls:
49+
- "https://example.com/advisory"
50+
cwe_ids:
51+
- "CWE-79"
52+
identifiers:
53+
- "CVE-2022-0001"
54+
"""
55+
)
56+
return tmp_path
57+
58+
59+
def test_clone(mock_fetch_via_vcs, mock_vcs_response):
60+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
61+
62+
pipeline = GitLabImporterPipeline()
63+
pipeline.clone()
64+
65+
mock_fetch_via_vcs.assert_called_once_with(pipeline.repo_url)
66+
assert pipeline.vcs_response == mock_vcs_response
67+
68+
69+
def test_advisories_count(mock_gitlab_yaml, mock_vcs_response, mock_fetch_via_vcs):
70+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
71+
72+
mock_vcs_response.dest_dir = str(mock_gitlab_yaml)
73+
74+
pipeline = GitLabImporterPipeline()
75+
pipeline.clone()
76+
mock_fetch_via_vcs.assert_called_once()
77+
78+
count = pipeline.advisories_count()
79+
assert count == 1
80+
81+
82+
def test_collect_advisories(mock_gitlab_yaml, mock_vcs_response, mock_fetch_via_vcs):
83+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
84+
85+
mock_vcs_response.dest_dir = str(mock_gitlab_yaml)
86+
87+
pipeline = GitLabImporterPipeline()
88+
pipeline.clone()
89+
90+
advisories = list(pipeline.collect_advisories())
91+
assert len(advisories) == 1
92+
advisory = advisories[0]
93+
94+
assert isinstance(advisory, AdvisoryData)
95+
assert advisory.advisory_id == "CVE-2022-0001"
96+
assert advisory.summary == "Example vulnerability\nExample description"
97+
assert advisory.references_v2[0].url == "https://example.com/advisory"
98+
assert advisory.affected_packages[0].package.name == "package-name"
99+
assert advisory.affected_packages[0].fixed_version
100+
assert advisory.weaknesses[0] == 79
101+
102+
103+
def test_clean_downloads(mock_vcs_response):
104+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
105+
106+
pipeline = GitLabImporterPipeline()
107+
pipeline.vcs_response = mock_vcs_response
108+
109+
pipeline.clean_downloads()
110+
mock_vcs_response.delete.assert_called_once()
111+
112+
113+
def test_on_failure(mock_vcs_response):
114+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
115+
116+
pipeline = GitLabImporterPipeline()
117+
pipeline.vcs_response = mock_vcs_response
118+
119+
with patch.object(pipeline, "clean_downloads") as mock_clean:
120+
pipeline.on_failure()
121+
mock_clean.assert_called_once()
122+
123+
124+
def test_collect_advisories_with_invalid_yaml(
125+
mock_gitlab_yaml, mock_vcs_response, mock_fetch_via_vcs
126+
):
127+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
128+
129+
# Add an invalid YAML file
130+
invalid_file = Path(mock_gitlab_yaml) / "pypi" / "package_name" / "invalid.yml"
131+
invalid_file.write_text(":::invalid_yaml")
132+
133+
mock_vcs_response.dest_dir = str(mock_gitlab_yaml)
134+
135+
pipeline = GitLabImporterPipeline()
136+
pipeline.clone()
137+
138+
# Should not raise but skip invalid YAML
139+
advisories = list(pipeline.collect_advisories())
140+
assert len(advisories) == 1 # Only one valid advisory is parsed
141+
142+
143+
def test_advisories_count_empty(mock_vcs_response, mock_fetch_via_vcs, tmp_path):
144+
from vulnerabilities.pipelines.v2_importers.gitlab_importer import GitLabImporterPipeline
145+
146+
mock_vcs_response.dest_dir = str(tmp_path)
147+
148+
pipeline = GitLabImporterPipeline()
149+
pipeline.clone()
150+
mock_fetch_via_vcs.assert_called_once()
151+
152+
count = pipeline.advisories_count()
153+
assert count == 0

0 commit comments

Comments
 (0)