1717
1818
1919from json import loads as json_loads
20+ from os .path import join
2021from typing import Any , Callable
2122from unittest import TestCase
2223from unittest .mock import patch
2324
24- from ddt import ddt , named_data
25+ from ddt import data , ddt , named_data
2526
2627from cyclonedx .model .bom import Bom
28+ from cyclonedx .model .license import DisjunctiveLicense , LicenseExpression , LicenseRepository
2729from cyclonedx .schema import OutputFormat , SchemaVersion
28- from tests import DeepCompareMixin , SnapshotMixin , mksname , uuid_generator
30+ from tests import OWN_DATA_DIRECTORY , DeepCompareMixin , SnapshotMixin , mksname , uuid_generator
2931from tests ._data .models import all_get_bom_funct_valid , all_get_bom_funct_with_incomplete_deps
3032
3133
@@ -35,11 +37,38 @@ class TestDeserializeJson(TestCase, SnapshotMixin, DeepCompareMixin):
3537 @named_data (* all_get_bom_funct_valid )
3638 @patch ('cyclonedx.model.ThisTool._version' , 'TESTING' )
3739 @patch ('cyclonedx.model.bom_ref.uuid4' , side_effect = uuid_generator (0 , version = 4 ))
38- def test (self , get_bom : Callable [[], Bom ], * _ : Any , ** __ : Any ) -> None :
40+ def test_prepared (self , get_bom : Callable [[], Bom ], * _ : Any , ** __ : Any ) -> None :
3941 # only latest schema will have all data populated in serialized form
4042 snapshot_name = mksname (get_bom , SchemaVersion .V1_4 , OutputFormat .JSON )
4143 expected = get_bom ()
4244 json = json_loads (self .readSnapshot (snapshot_name ))
4345 bom = Bom .from_json (json )
4446 self .assertBomDeepEqual (expected , bom ,
4547 fuzzy_deps = get_bom in all_get_bom_funct_with_incomplete_deps )
48+
49+ @data (SchemaVersion .V1_4 , SchemaVersion .V1_3 , SchemaVersion .V1_2 )
50+ def test_mixed_licenses_before15 (self , sv : SchemaVersion ) -> None :
51+ # before CDX 1.5 it was allowed to mix `expression` and `license`
52+ def test (ls : LicenseRepository ) -> None :
53+ self .assertEqual (3 , len (ls ))
54+ expression : LicenseExpression = next ((
55+ li for li in ls if isinstance (li , LicenseExpression )
56+ ), None )
57+ with_id : DisjunctiveLicense = next ((
58+ li for li in ls if isinstance (li , DisjunctiveLicense ) and li .id is not None
59+ ), None )
60+ with_name : DisjunctiveLicense = next ((
61+ li for li in ls if isinstance (li , DisjunctiveLicense ) and li .name is not None
62+ ), None )
63+ self .assertEqual ('MIT OR Apache-2.0' , expression .value )
64+ self .assertEqual ('MIT' , with_id .id )
65+ self .assertEqual ('foo license' , with_name .name )
66+
67+ json_file = join (OWN_DATA_DIRECTORY , 'json' , sv .to_version (), 'bom_with_mixed_licenses.json' )
68+ with open (json_file ) as f :
69+ json = json_loads (f .read ())
70+ bom : Bom = Bom .from_json (json )
71+ test (bom .metadata .licenses )
72+ test (bom .metadata .component .licenses )
73+ test (list (bom .components )[0 ].licenses )
74+ test (list (bom .services )[0 ].licenses )
0 commit comments