3636import io .github .guacsec .trustifyda .api .v5 .Scanned ;
3737import io .github .guacsec .trustifyda .api .v5 .Source ;
3838import io .github .guacsec .trustifyda .api .v5 .SourceSummary ;
39+ import io .github .guacsec .trustifyda .image .Image ;
40+ import io .github .guacsec .trustifyda .image .ImageRef ;
3941import io .github .guacsec .trustifyda .image .ImageUtils ;
4042import io .github .guacsec .trustifyda .impl .ExhortApi ;
43+ import io .github .guacsec .trustifyda .providers .DockerfileProvider ;
4144import java .io .IOException ;
4245import java .lang .reflect .Method ;
4346import java .nio .file .Path ;
4447import java .nio .file .Paths ;
4548import java .util .HashMap ;
4649import java .util .HashSet ;
50+ import java .util .LinkedHashSet ;
4751import java .util .Map ;
4852import java .util .Set ;
4953import java .util .concurrent .CompletableFuture ;
@@ -836,6 +840,9 @@ void executeImageAnalysis_with_json_format_should_complete_successfully() throws
836840 Set <io .github .guacsec .trustifyda .image .ImageRef > imageRefs = new HashSet <>();
837841 io .github .guacsec .trustifyda .image .ImageRef mockImageRef =
838842 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
843+ Image mockImage = mock (Image .class );
844+ when (mockImage .getFullName ()).thenReturn ("nginx:latest" );
845+ when (mockImageRef .getImage ()).thenReturn (mockImage );
839846 imageRefs .add (mockImageRef );
840847
841848 Map <io .github .guacsec .trustifyda .image .ImageRef , AnalysisReport > mockResults = new HashMap <>();
@@ -897,6 +904,9 @@ void executeImageAnalysis_with_summary_format_should_complete_successfully() thr
897904 Set <io .github .guacsec .trustifyda .image .ImageRef > imageRefs = new HashSet <>();
898905 io .github .guacsec .trustifyda .image .ImageRef mockImageRef =
899906 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
907+ Image mockImage = mock (Image .class );
908+ when (mockImage .getFullName ()).thenReturn ("nginx:latest" );
909+ when (mockImageRef .getImage ()).thenReturn (mockImage );
900910 imageRefs .add (mockImageRef );
901911
902912 Map <io .github .guacsec .trustifyda .image .ImageRef , AnalysisReport > mockResults = new HashMap <>();
@@ -927,7 +937,9 @@ void executeImageAnalysis_with_summary_format_should_complete_successfully() thr
927937 void formatImageAnalysisResult_should_serialize_to_json () throws Exception {
928938 io .github .guacsec .trustifyda .image .ImageRef mockImageRef =
929939 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
930- when (mockImageRef .toString ()).thenReturn ("nginx:latest" );
940+ Image mockImage = mock (Image .class );
941+ when (mockImage .getFullName ()).thenReturn ("nginx:latest" );
942+ when (mockImageRef .getImage ()).thenReturn (mockImage );
931943
932944 Map <io .github .guacsec .trustifyda .image .ImageRef , AnalysisReport > analysisResults =
933945 new HashMap <>();
@@ -949,8 +961,12 @@ void extractImageSummary_should_extract_summaries_for_all_images() throws Except
949961 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
950962 io .github .guacsec .trustifyda .image .ImageRef mockImageRef2 =
951963 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
952- when (mockImageRef1 .toString ()).thenReturn ("nginx:latest" );
953- when (mockImageRef2 .toString ()).thenReturn ("redis:alpine" );
964+ Image mockImage1 = mock (Image .class );
965+ when (mockImage1 .getFullName ()).thenReturn ("nginx:latest" );
966+ when (mockImageRef1 .getImage ()).thenReturn (mockImage1 );
967+ Image mockImage2 = mock (Image .class );
968+ when (mockImage2 .getFullName ()).thenReturn ("redis:alpine" );
969+ when (mockImageRef2 .getImage ()).thenReturn (mockImage2 );
954970
955971 Map <io .github .guacsec .trustifyda .image .ImageRef , AnalysisReport > analysisResults =
956972 new HashMap <>();
@@ -975,6 +991,9 @@ void executeCommand_with_image_analysis_should_complete_successfully() throws Ex
975991 Set <io .github .guacsec .trustifyda .image .ImageRef > imageRefs = new HashSet <>();
976992 io .github .guacsec .trustifyda .image .ImageRef mockImageRef =
977993 mock (io .github .guacsec .trustifyda .image .ImageRef .class );
994+ Image mockImage = mock (Image .class );
995+ when (mockImage .getFullName ()).thenReturn ("nginx:latest" );
996+ when (mockImageRef .getImage ()).thenReturn (mockImage );
978997 imageRefs .add (mockImageRef );
979998
980999 CliArgs imageArgs = new CliArgs (Command .IMAGE , imageRefs , OutputFormat .JSON );
@@ -1104,4 +1123,109 @@ void parseCommand_with_sbom_should_return_sbom_command() throws Exception {
11041123 Command result = (Command ) parseCommandMethod .invoke (null , "sbom" );
11051124 assertThat (result ).isEqualTo (Command .SBOM );
11061125 }
1126+
1127+ @ Test
1128+ void executeCommand_with_stack_dockerfile_routes_to_image_analysis () throws Exception {
1129+ CliArgs args =
1130+ new CliArgs (Command .STACK , Paths .get ("/test/path/Dockerfile" ), OutputFormat .JSON );
1131+
1132+ ImageRef mockImageRef = mock (ImageRef .class );
1133+ Image mockImage = mock (Image .class );
1134+ when (mockImage .getFullName ()).thenReturn ("node:22" );
1135+ when (mockImageRef .getImage ()).thenReturn (mockImage );
1136+ Set <ImageRef > imageRefs = new LinkedHashSet <>();
1137+ imageRefs .add (mockImageRef );
1138+
1139+ Map <ImageRef , AnalysisReport > mockResults = new HashMap <>();
1140+ mockResults .put (mockImageRef , defaultAnalysisReport ());
1141+
1142+ try (MockedStatic <DockerfileProvider > dockerMock = mockStatic (DockerfileProvider .class );
1143+ MockedConstruction <ExhortApi > mockedExhortApi =
1144+ mockConstruction (
1145+ ExhortApi .class ,
1146+ (mock , context ) -> {
1147+ when (mock .imageAnalysis (any (Set .class )))
1148+ .thenReturn (CompletableFuture .completedFuture (mockResults ));
1149+ })) {
1150+
1151+ dockerMock
1152+ .when (() -> DockerfileProvider .parseImageRefs (any (Path .class )))
1153+ .thenReturn (imageRefs );
1154+
1155+ Method executeCommandMethod = App .class .getDeclaredMethod ("executeCommand" , CliArgs .class );
1156+ executeCommandMethod .setAccessible (true );
1157+
1158+ CompletableFuture <String > result =
1159+ (CompletableFuture <String >) executeCommandMethod .invoke (null , args );
1160+
1161+ assertThat (result ).isNotNull ();
1162+ assertThat (result .get ()).isNotNull ();
1163+ dockerMock .verify (() -> DockerfileProvider .parseImageRefs (any (Path .class )));
1164+ }
1165+ }
1166+
1167+ @ Test
1168+ void executeCommand_with_component_dockerfile_routes_to_image_analysis () throws Exception {
1169+ CliArgs args =
1170+ new CliArgs (Command .COMPONENT , Paths .get ("/test/path/Dockerfile" ), OutputFormat .JSON );
1171+
1172+ ImageRef mockImageRef = mock (ImageRef .class );
1173+ Image mockImage = mock (Image .class );
1174+ when (mockImage .getFullName ()).thenReturn ("node:22" );
1175+ when (mockImageRef .getImage ()).thenReturn (mockImage );
1176+ Set <ImageRef > imageRefs = new LinkedHashSet <>();
1177+ imageRefs .add (mockImageRef );
1178+
1179+ Map <ImageRef , AnalysisReport > mockResults = new HashMap <>();
1180+ mockResults .put (mockImageRef , defaultAnalysisReport ());
1181+
1182+ try (MockedStatic <DockerfileProvider > dockerMock = mockStatic (DockerfileProvider .class );
1183+ MockedConstruction <ExhortApi > mockedExhortApi =
1184+ mockConstruction (
1185+ ExhortApi .class ,
1186+ (mock , context ) -> {
1187+ when (mock .imageAnalysis (any (Set .class )))
1188+ .thenReturn (CompletableFuture .completedFuture (mockResults ));
1189+ })) {
1190+
1191+ dockerMock
1192+ .when (() -> DockerfileProvider .parseImageRefs (any (Path .class )))
1193+ .thenReturn (imageRefs );
1194+
1195+ Method executeCommandMethod = App .class .getDeclaredMethod ("executeCommand" , CliArgs .class );
1196+ executeCommandMethod .setAccessible (true );
1197+
1198+ CompletableFuture <String > result =
1199+ (CompletableFuture <String >) executeCommandMethod .invoke (null , args );
1200+
1201+ assertThat (result ).isNotNull ();
1202+ assertThat (result .get ()).isNotNull ();
1203+ dockerMock .verify (() -> DockerfileProvider .parseImageRefs (any (Path .class )));
1204+ }
1205+ }
1206+
1207+ @ Test
1208+ void executeCommand_with_stack_non_dockerfile_uses_stack_analysis () throws Exception {
1209+ CliArgs args = new CliArgs (Command .STACK , TEST_FILE , OutputFormat .JSON );
1210+
1211+ AnalysisReport mockReport = mock (AnalysisReport .class );
1212+
1213+ try (MockedConstruction <ExhortApi > mockedExhortApi =
1214+ mockConstruction (
1215+ ExhortApi .class ,
1216+ (mock , context ) -> {
1217+ when (mock .stackAnalysis (any (String .class )))
1218+ .thenReturn (CompletableFuture .completedFuture (mockReport ));
1219+ })) {
1220+
1221+ Method executeCommandMethod = App .class .getDeclaredMethod ("executeCommand" , CliArgs .class );
1222+ executeCommandMethod .setAccessible (true );
1223+
1224+ CompletableFuture <String > result =
1225+ (CompletableFuture <String >) executeCommandMethod .invoke (null , args );
1226+
1227+ assertThat (result ).isNotNull ();
1228+ assertThat (result .get ()).isNotNull ();
1229+ }
1230+ }
11071231}
0 commit comments