Skip to content

Commit b227c16

Browse files
authored
Merge pull request #70 from Jalen-Stephens/52-expand-automated-testing-unit-api-integration-to-80-branch-coverage
52 expand automated testing unit api integration to 80 branch coverage
2 parents e696e4a + 1292ba8 commit b227c16

21 files changed

+1322
-112
lines changed

.DS_Store

-6 KB
Binary file not shown.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@ client/.cache/
4747

4848
### Output.json ###
4949
output.json
50+
51+
.DS_Store

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@
244244
<version>0.8.12</version>
245245
<executions>
246246
<execution>
247-
<id>prepare-agent</id>
247+
<!-- Attach JaCoCo agent to test phase to collect coverage -->
248248
<goals>
249249
<goal>prepare-agent</goal>
250250
</goals>

reports/pmd-after-fix.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<!DOCTYPE html>
2+
<!--
3+
| Generated by Apache Maven Doxia Site Renderer 1.11.1 at 2025-11-29
4+
5+
| Rendered using Apache Maven Default Skin
6+
-->
7+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
8+
<head>
9+
<meta charset="UTF-8" />
10+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
11+
<meta name="generator" content="Apache Maven Doxia Site Renderer 1.11.1" />
12+
<title>MetaDetect AI Image Detection Service &#x2013; PMD Results</title>
13+
<link rel="stylesheet" href="./css/maven-base.css" />
14+
<link rel="stylesheet" href="./css/maven-theme.css" />
15+
<link rel="stylesheet" href="./css/site.css" />
16+
<link rel="stylesheet" href="./css/print.css" media="print" />
17+
</head>
18+
<body class="composite">
19+
<div id="banner">
20+
<div class="clear">
21+
<hr/>
22+
</div>
23+
</div>
24+
<div id="breadcrumbs">
25+
<div class="xleft">
26+
<span id="publishDate">Last Published: 2025-11-29</span>
27+
| <span id="projectVersion">Version: 0.1.0</span>
28+
</div>
29+
<div class="xright"> </div>
30+
<div class="clear">
31+
<hr/>
32+
</div>
33+
</div>
34+
<div id="leftColumn">
35+
<div id="navcolumn">
36+
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
37+
<img class="poweredBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
38+
</a>
39+
</div>
40+
</div>
41+
<div id="bodyColumn">
42+
<div id="contentBox">
43+
<section>
44+
<h2><a name="PMD_Results"></a>PMD Results</h2><a name="PMD_Results"></a>
45+
<p>The following document contains the results of <a class="externalLink" href="https://pmd.github.io">PMD</a> 6.55.0.</p>
46+
<p>PMD found no problems in your source code.</p></section>
47+
</div>
48+
</div>
49+
<div class="clear">
50+
<hr/>
51+
</div>
52+
<div id="footer">
53+
<div class="xright">
54+
Copyright &#169; 2025.. </div>
55+
<div class="clear">
56+
<hr/>
57+
</div>
58+
</div>
59+
</body>
60+
</html>

reports/pmd-after-fix.log

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[INFO] Scanning for projects...
2+
[INFO] ------------------------------------------------------------------------
3+
[INFO] Detecting the operating system and CPU architecture
4+
[INFO] ------------------------------------------------------------------------
5+
[INFO] os.detected.name: osx
6+
[INFO] os.detected.arch: aarch_64
7+
[INFO] os.detected.bitness: 64
8+
[INFO] os.detected.version: 15.6
9+
[INFO] os.detected.version.major: 15
10+
[INFO] os.detected.version.minor: 6
11+
[INFO] os.detected.classifier: osx-aarch_64
12+
[INFO]
13+
[INFO] --------------< dev.coms4156.project:metadetect-service >---------------
14+
[INFO] Building MetaDetect AI Image Detection Service 0.1.0
15+
[INFO] from pom.xml
16+
[INFO] --------------------------------[ jar ]---------------------------------
17+
[INFO]
18+
[INFO] >>> pmd:3.21.2:check (default-cli) > :pmd @ metadetect-service >>>
19+
[INFO]
20+
[INFO] --- pmd:3.21.2:pmd (pmd) @ metadetect-service ---
21+
[WARNING] Unable to locate Source XRef to link to - DISABLED
22+
[INFO] PMD version: 6.55.0
23+
[INFO] Rendering content with org.apache.maven.skins:maven-default-skin:jar:1.3 skin.
24+
[INFO]
25+
[INFO] <<< pmd:3.21.2:check (default-cli) < :pmd @ metadetect-service <<<
26+
[INFO]
27+
[INFO]
28+
[INFO] --- pmd:3.21.2:check (default-cli) @ metadetect-service ---
29+
[INFO] PMD version: 6.55.0
30+
[INFO]
31+
[INFO] ------------------------------------------------------------------------
32+
[INFO] BUILD SUCCESS
33+
[INFO] ------------------------------------------------------------------------
34+
[INFO] Total time: 1.999 s
35+
[INFO] Finished at: 2025-11-29T12:23:45-05:00
36+
[INFO] ------------------------------------------------------------------------

reports/pmd-with-issues.html

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<!DOCTYPE html>
2+
<!--
3+
| Generated by Apache Maven Doxia Site Renderer 1.11.1 at 2025-11-29
4+
5+
| Rendered using Apache Maven Default Skin
6+
-->
7+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
8+
<head>
9+
<meta charset="UTF-8" />
10+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
11+
<meta name="generator" content="Apache Maven Doxia Site Renderer 1.11.1" />
12+
<title>MetaDetect AI Image Detection Service &#x2013; PMD Results</title>
13+
<link rel="stylesheet" href="./css/maven-base.css" />
14+
<link rel="stylesheet" href="./css/maven-theme.css" />
15+
<link rel="stylesheet" href="./css/site.css" />
16+
<link rel="stylesheet" href="./css/print.css" media="print" />
17+
</head>
18+
<body class="composite">
19+
<div id="banner">
20+
<div class="clear">
21+
<hr/>
22+
</div>
23+
</div>
24+
<div id="breadcrumbs">
25+
<div class="xleft">
26+
<span id="publishDate">Last Published: 2025-11-29</span>
27+
| <span id="projectVersion">Version: 0.1.0</span>
28+
</div>
29+
<div class="xright"> </div>
30+
<div class="clear">
31+
<hr/>
32+
</div>
33+
</div>
34+
<div id="leftColumn">
35+
<div id="navcolumn">
36+
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
37+
<img class="poweredBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
38+
</a>
39+
</div>
40+
</div>
41+
<div id="bodyColumn">
42+
<div id="contentBox">
43+
<section>
44+
<h2><a name="PMD_Results"></a>PMD Results</h2><a name="PMD_Results"></a>
45+
<p>The following document contains the results of <a class="externalLink" href="https://pmd.github.io">PMD</a> 6.55.0.</p><section>
46+
<h3><a name="Violations_By_Priority"></a>Violations By Priority</h3><a name="Violations_By_Priority"></a><section>
47+
<h4><a name="Priority_3"></a>Priority 3</h4><a name="Priority_3"></a><section>
48+
<h5><a name="dev.2Fcoms4156.2Fproject.2Fmetadetect.2Fservice.2FAnalyzeService.java"></a>dev/coms4156/project/metadetect/service/AnalyzeService.java</h5><a name="dev.2Fcoms4156.2Fproject.2Fmetadetect.2Fservice.2FAnalyzeService.java"></a>
49+
<table border="0" class="bodyTable">
50+
<tr class="a">
51+
<th>Rule</th>
52+
<th>Violation</th>
53+
<th>Line</th></tr>
54+
<tr class="b">
55+
<td align="left"><a class="externalLink" href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatemethod">UnusedPrivateMethod</a></td>
56+
<td>Avoid unused private methods such as 'swallowExceptionDemo(File)'.</td>
57+
<td>342</td></tr>
58+
<tr class="a">
59+
<td align="left"><a class="externalLink" href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_errorprone.html#emptycatchblock">EmptyCatchBlock</a></td>
60+
<td>Avoid empty catch blocks</td>
61+
<td>345&#x2013;346</td></tr></table></section></section></section><section>
62+
<h3><a name="Files"></a>Files</h3><a name="Files"></a><section>
63+
<h4><a name="dev.2Fcoms4156.2Fproject.2Fmetadetect.2Fservice.2FAnalyzeService.java"></a>dev/coms4156/project/metadetect/service/AnalyzeService.java</h4><a name="dev.2Fcoms4156.2Fproject.2Fmetadetect.2Fservice.2FAnalyzeService.java"></a>
64+
<table border="0" class="bodyTable">
65+
<tr class="a">
66+
<th>Rule</th>
67+
<th>Violation</th>
68+
<th>Priority</th>
69+
<th>Line</th></tr>
70+
<tr class="b">
71+
<td align="left"><a class="externalLink" href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_bestpractices.html#unusedprivatemethod">UnusedPrivateMethod</a></td>
72+
<td>Avoid unused private methods such as 'swallowExceptionDemo(File)'.</td>
73+
<td>3</td>
74+
<td>342</td></tr>
75+
<tr class="a">
76+
<td align="left"><a class="externalLink" href="https://pmd.github.io/pmd-6.55.0/pmd_rules_java_errorprone.html#emptycatchblock">EmptyCatchBlock</a></td>
77+
<td>Avoid empty catch blocks</td>
78+
<td>3</td>
79+
<td>345&#x2013;346</td></tr></table></section></section></section>
80+
</div>
81+
</div>
82+
<div class="clear">
83+
<hr/>
84+
</div>
85+
<div id="footer">
86+
<div class="xright">
87+
Copyright &#169; 2025.. </div>
88+
<div class="clear">
89+
<hr/>
90+
</div>
91+
</div>
92+
</body>
93+
</html>

reports/pmd-with-issues.log

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-pmd-plugin:3.21.2:check (default-cli) on project metadetect-service: You have 2 PMD violations. For more details see: /Users/jalenstephens/Desktop/ADV-SWE-Project/target/pmd.xml -> [Help 1]
2+
[ERROR]
3+
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
4+
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
5+
[ERROR]
6+
[ERROR] For more information about the errors and possible solutions, please read the following articles:
7+
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
MetaDetect Test Partitions
2+
=========================
3+
4+
This document enumerates the equivalence partitions and boundaries exercised by the automated tests. Test method names are referenced so the mapping is explicit.
5+
6+
Unit-Level Partitions
7+
---------------------
8+
- AnalyzeService
9+
- Storage path present vs missing: `submitAnalysis_happyPath...`, `submitAnalysis_missingStoragePath_throws400`.
10+
- Ownership success vs Forbidden/NotFound: `submitAnalysis_propagatesOwnershipErrors`, `compare_forbiddenOnLeft_propagates`.
11+
- Download success vs empty/IO failure: `downloadToTemp_fileUrl_intoProvidedDir_copiesBytes`, `downloadToTemp_withoutExtension_defaultsToBinExtension_andFailsOnEmpty`.
12+
- C2PA success vs runtime failure: `submitAnalysis_happyPath_marksCompleted_andReturnsId`, `submitAnalysis_c2paFailure_marksFailed`.
13+
- Analysis lookup present vs missing manifest vs missing row: `getMetadata_success...`, `getMetadata_missing_throws404`, `getMetadata_notFound_throws404`, `getConfidence_missingAnalysis_throwsNotFound`.
14+
- Utility bounds: `truncate_*` (null, under-limit, over-limit) and `escapeForJson_escapesControlCharacters`.
15+
16+
- SupabaseStorageService
17+
- Upload content-type provided vs default: `uploadObject_putsRawBytesToCorrectPath_withAuthAndApikeyHeaders`.
18+
- Signed URL parsing valid vs malformed/null: `createSignedUrl_returnsAbsoluteProjectUrl_andSendsHeaders`, `extractSignedUrlFromJson_handlesMalformed`.
19+
- Delete path blank vs 404 vs success: `deleteObject_ignoresBlankPath`, `deleteObject_404IsSwallowed`.
20+
21+
- C2paToolInvoker
22+
- Manifest present with active id + AI generator vs empty manifests: `parseMetadata_detectsActiveManifest_andAiGenerator`, `parseMetadata_noManifest_setsFlagsToZero`.
23+
- Invalid JSON / CLI failures: `parseMetadata_invalidJson_setsErrorFlag`, `extractMetadata_cliFailure_setsErrorFlag`, `extractMetadata_nullFile_returnsError`.
24+
25+
- FeatureExtractor
26+
- Missing image path -> C2PA-only defaults: `extractAllFeatures_missingFile_returnsC2paOnly`.
27+
- Small matrix feature computations (Laplace, noise, edges, frequency, entropy) -> non-negative bounds: `featureMethods_handleSmallMatrix`.
28+
29+
- DTO shape/record coverage: `DtosTest.recordsRoundTrip` covers all request/response records including nullables and collections.
30+
31+
API/Controller Partitions
32+
-------------------------
33+
- /api/analyze
34+
- POST valid image id -> 202 payload: `submit_returnsAcceptedWithBody`.
35+
- GET status success vs invalid UUID: `getStatus_returnsDtoFromService`, `getStatus_invalidUuid_returns400`.
36+
- GET manifest success: `getManifest_returnsManifestJson`.
37+
- GET compare: both params present vs missing `right`: `compare_returnsComparisonResult`, `compare_missingParam_returnsBadRequest`.
38+
39+
- /auth
40+
- Signup/login/refresh happy paths: `signup_ok`, `login_ok`, `refresh_ok`.
41+
- Refresh missing token partition (controller validation) vs framework-invalid body: `refresh_missing_field_400_controller`, `refresh_empty_body_400_framework`.
42+
- Proxy error bubble-up: `proxy_error_bubbled`, `proxy_error_handler_sets_json`.
43+
- /auth/me authenticated with/without email vs unauthenticated: `me_authenticated_ok`, `me_authenticated_email_null`, `me_unauthenticated_401`.
44+
- Method/MediaType boundaries: `signup_method_not_allowed_405`, `signup_invalid_json_400`, `login_unsupported_media_type_415`.
45+
46+
- /api/images
47+
- List empty/out-of-range vs populated: `listImages_outOfRangePagination_returnsEmptyList`, `listImages_success`.
48+
- Get found vs not found vs forbidden: `getImage_success`, `getImage_notFound`, `getImage_forbidden`.
49+
- Update with partial fields vs note/labels change: `updateImage_success`, `updateImage_blankFilename_isIgnored_butOtherFieldsApply`.
50+
- Upload multipart success: `upload_success_returns201AndPersistsStoragePath`.
51+
- Signed URL fetch: `signedUrl_success_returns200WithUrl`.
52+
53+
- Security/CORS/JWT
54+
- Public vs secured resources and CORS preflight: `publicEndpoints_noAuthRequired`, `optionsPreflight_corsHeaders`.
55+
- JWT issuer boundaries (with/without slash, wrong issuer): `jwtDecoder_validIssuer_noSlash`, `jwtDecoder_validIssuer_withSlash`, `jwtDecoder_wrongIssuer_rejected`.
56+
57+
Integration Tests
58+
-----------------
59+
- `C2paToolInvokerIntegrationTest` and `AnalyzeServiceC2paIntegrationTest`: real c2patool binary when present (external CLI integration).
60+
- `SupabaseStorageServiceTest` uses `MockWebServer` to exercise HTTP-level integration (multiple clients + logging).
61+
- `ClientServiceLiveE2eTest` (opt-in via `LIVE_E2E=true`): full stack against real Supabase auth/storage/database.
62+
63+
Coverage Goal
64+
-------------
65+
All tests run in the Maven `test` phase and are wired for JaCoCo. The above partitions intentionally cover valid/invalid inputs and boundary conditions to drive branch coverage above the 80% requirement.

src/main/java/dev/coms4156/project/metadetect/service/FeatureExtractor.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.opencv.core.Size;
1313
import org.opencv.imgcodecs.Imgcodecs;
1414
import org.opencv.imgproc.Imgproc;
15+
import nu.pattern.OpenCV;
1516

1617

1718
/**
@@ -31,8 +32,18 @@
3132
public class FeatureExtractor {
3233

3334
static {
34-
// Load native OpenCV library
35-
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
35+
// Load native OpenCV library packaged with openpnp/opencv.
36+
try {
37+
OpenCV.loadLocally();
38+
} catch (Throwable t) {
39+
// Fallback to shared loader if local extraction is not available.
40+
try {
41+
OpenCV.loadShared();
42+
} catch (Throwable ignored) {
43+
// Last resort: try the default system library name.
44+
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
45+
}
46+
}
3647
}
3748

3849
/**
@@ -57,7 +68,7 @@ public double[] extractAllFeatures(String imagePath, C2paMetadata c2pa) {
5768

5869
int width = img.cols();
5970
int height = img.rows();
60-
double aspectRatio = (height == 0) ? 0.0 : (double) width / height;
71+
double aspectRatio = aspectRatio(width, height);
6172

6273
return new double[] {
6374
lapVar,
@@ -91,6 +102,11 @@ private double[] generateEmpty(C2paMetadata c2pa) {
91102
};
92103
}
93104

105+
/** Computes aspect ratio while guarding against zero height. */
106+
private static double aspectRatio(int width, int height) {
107+
return height == 0 ? 0.0 : (double) width / height;
108+
}
109+
94110
/**
95111
* Laplacian Variance (Sharpness).
96112
*

0 commit comments

Comments
 (0)