12
12
import unittest
13
13
from datetime import datetime
14
14
from pathlib import Path
15
+ from unittest .mock import MagicMock , call , patch
15
16
16
17
from jsonschema import validate
17
18
from rich .console import Console
@@ -1101,6 +1102,10 @@ class TestOutputEngine(unittest.TestCase):
1101
1102
]
1102
1103
1103
1104
def setUp (self ) -> None :
1105
+ self .all_product_data = [
1106
+ ProductInfo (product = "product1" , version = "1.0" , vendor = "VendorA" ),
1107
+ ProductInfo (product = "product2" , version = "2.0" , vendor = "unknown" ),
1108
+ ]
1104
1109
self .output_engine = OutputEngine (
1105
1110
all_cve_data = self .MOCK_OUTPUT ,
1106
1111
scanned_dir = "" ,
@@ -1111,6 +1116,68 @@ def setUp(self) -> None:
1111
1116
)
1112
1117
self .mock_file = tempfile .NamedTemporaryFile ("w+" , encoding = "utf-8" )
1113
1118
1119
+ def test_generate_sbom (self ):
1120
+ with patch (
1121
+ "cve_bin_tool.output_engine.SBOMPackage"
1122
+ ) as mock_sbom_package , patch ("cve_bin_tool.output_engine.SBOMRelationship" ):
1123
+ mock_package_instance = MagicMock ()
1124
+ mock_sbom_package .return_value = mock_package_instance
1125
+
1126
+ self .output_engine .generate_sbom (
1127
+ all_product_data = self .all_product_data ,
1128
+ filename = "test.sbom" ,
1129
+ sbom_type = "spdx" ,
1130
+ sbom_format = "tag" ,
1131
+ sbom_root = "CVE-SCAN" ,
1132
+ )
1133
+
1134
+ # Assertions
1135
+ mock_package_instance .set_name .assert_any_call ("CVEBINTOOL-CVE-SCAN" )
1136
+
1137
+ # Check if set_name is called for each product
1138
+ expected_calls = [
1139
+ call (product .product ) for product in self .all_product_data
1140
+ ]
1141
+ mock_package_instance .set_name .assert_has_calls (
1142
+ expected_calls , any_order = True
1143
+ )
1144
+
1145
+ # Check if set_version is called for each product
1146
+ expected_calls = [
1147
+ call (product .version ) for product in self .all_product_data
1148
+ ]
1149
+ mock_package_instance .set_version .assert_has_calls (
1150
+ expected_calls , any_order = True
1151
+ )
1152
+
1153
+ # Check if set_supplier is called for VendorA
1154
+ mock_package_instance .set_supplier .assert_any_call (
1155
+ "Organization" , "VendorA"
1156
+ )
1157
+
1158
+ for call_args in mock_package_instance .set_supplier .call_args_list :
1159
+ args , _ = call_args
1160
+ self .assertNotEqual (args , ("Organization" , "unknown" ))
1161
+
1162
+ # Check if set_licensedeclared and set_licenseconcluded are called for each product
1163
+ expected_calls = [call ("NOASSERTION" )] * len (self .all_product_data )
1164
+ mock_package_instance .set_licensedeclared .assert_has_calls (
1165
+ expected_calls , any_order = True
1166
+ )
1167
+ mock_package_instance .set_licenseconcluded .assert_has_calls (
1168
+ expected_calls , any_order = True
1169
+ )
1170
+
1171
+ # Ensure packages are added to sbom_packages correctly
1172
+ expected_packages = {
1173
+ mock_package_instance .get_package .return_value ,
1174
+ mock_package_instance .get_package .return_value ,
1175
+ }
1176
+ actual_packages = [
1177
+ package for package in self .output_engine .sbom_packages .values ()
1178
+ ]
1179
+ self .assertEqual (actual_packages , list (expected_packages ))
1180
+
1114
1181
def tearDown (self ) -> None :
1115
1182
self .mock_file .close ()
1116
1183
0 commit comments