36
36
import com .google .gson .Gson ;
37
37
import java .io .FileOutputStream ;
38
38
import java .io .IOException ;
39
+ import java .nio .charset .StandardCharsets ;
39
40
import java .nio .file .Files ;
40
41
import java .nio .file .Path ;
41
42
import java .util .HashMap ;
42
43
import java .util .jar .JarOutputStream ;
43
44
import java .util .zip .ZipEntry ;
44
45
import org .junit .jupiter .api .BeforeEach ;
46
+ import org .junit .jupiter .api .Disabled ;
45
47
import org .junit .jupiter .api .Nested ;
46
48
import org .junit .jupiter .api .Test ;
47
49
import org .junit .jupiter .api .extension .ExtendWith ;
53
55
final class CodeArtifactsPactTest {
54
56
55
57
private Path jar ;
58
+ private Path metadataJson ;
56
59
57
60
/**
58
61
* Creates a test jar for the test to upload as a code artifact
@@ -65,6 +68,10 @@ void before(@TempDir final Path tmp) throws IOException {
65
68
try (JarOutputStream jos = new JarOutputStream (new FileOutputStream (jar .toFile ()))) {
66
69
jos .putNextEntry (new ZipEntry ("HelloWorld.class" ));
67
70
}
71
+ metadataJson = tmp .resolve ("prescan.json" );
72
+ try (FileOutputStream fos = new FileOutputStream (metadataJson .toFile ())) {
73
+ fos .write ("{\" test\" : \" data\" }" .getBytes (StandardCharsets .UTF_8 ));
74
+ }
68
75
}
69
76
70
77
/** Verifies the code artifact upload behavior. */
@@ -78,7 +85,7 @@ RequestResponsePact pact(final PactDslWithProvider builder) throws IOException {
78
85
params .put ("organizationId" , "organization-id" );
79
86
return builder
80
87
.given ("Projects Exist" , params )
81
- .uponReceiving ("upload new code artifact" )
88
+ .uponReceiving ("upload new code artifact with metadata " )
82
89
.method ("POST" )
83
90
.pathFromProviderState (
84
91
"/sast/organizations/${organizationId}/projects/${projectId}/code-artifacts" ,
@@ -115,14 +122,91 @@ void upload_code_artifact(final MockServer server) throws IOException {
115
122
.build ();
116
123
final Gson gson = GsonFactory .create ();
117
124
CodeArtifactClient client = new CodeArtifactClientImpl (contrast , gson , "organization-id" );
118
- final CodeArtifactInner codeArtifact = client .upload ("project-id" , jar );
125
+ final CodeArtifactInner codeArtifact = client .upload ("project-id" , jar , null );
126
+
127
+ final CodeArtifactInner expected =
128
+ CodeArtifactInner .builder ()
129
+ .id ("code-artifact-id" )
130
+ .projectId ("project-id" )
131
+ .organizationId ("organization-id" )
132
+ .filename (jar .getFileName ().toString ())
133
+ .createdTime (TestDataConstants .TIMESTAMP_EXAMPLE )
134
+ .build ();
135
+ assertThat (codeArtifact ).isEqualTo (expected );
136
+ }
137
+ }
138
+ /** Verifies the code artifact upload with metadata behavior. */
139
+ @ Nested
140
+ final class UploadCodeArtifactWithMetadata {
141
+
142
+ @ Disabled ("https://github.com/pact-foundation/pact-jvm/issues/668" )
143
+ @ Pact (consumer = "contrast-sdk" )
144
+ RequestResponsePact pact (final PactDslWithProvider builder ) throws IOException {
145
+
146
+ final HashMap <String , Object > params = new HashMap <>();
147
+ params .put ("id" , "project-id" );
148
+ params .put ("organizationId" , "organization-id" );
149
+ return builder
150
+ .given ("Projects Exist" , params )
151
+ .uponReceiving ("upload new code artifact" )
152
+ .method ("POST" )
153
+ .pathFromProviderState (
154
+ "/sast/organizations/${organizationId}/projects/${projectId}/code-artifacts" ,
155
+ "/sast/organizations/organization-id/projects/project-id/code-artifacts" )
156
+ .withFileUpload (
157
+ "filename" ,
158
+ jar .getFileName ().toString (),
159
+ "application/java-archive" ,
160
+ Files .readAllBytes (jar ))
161
+ // BUG: https://github.com/pact-foundation/pact-jvm/issues/668. Unable to define a PACT
162
+ // request matcher that
163
+ // has multiple multipart sections.
164
+ // Consumer interface definition is:
165
+ // https://github.com/Contrast-Security-Inc/sast-api-documentation/blob/master/sast-code-artifacts.yaml#L83
166
+ .withFileUpload (
167
+ "metadata" ,
168
+ metadataJson .getFileName ().toString (),
169
+ "application/json" ,
170
+ Files .readAllBytes (metadataJson ))
171
+ .willRespondWith ()
172
+ .status (201 )
173
+ .body (
174
+ newJsonBody (
175
+ o -> {
176
+ o .stringType ("id" , "code-artifact-id" );
177
+ o .valueFromProviderState ("projectId" , "${projectId}" , "project-id" );
178
+ o .valueFromProviderState (
179
+ "organizationId" , "${organizationId}" , "organization-id" );
180
+ o .stringType ("filename" , jar .getFileName ().toString ());
181
+ o .stringType ("metadata" , metadataJson .getFileName ().toString ());
182
+ o .datetime (
183
+ "createdTime" ,
184
+ PactConstants .DATETIME_FORMAT ,
185
+ TestDataConstants .TIMESTAMP_EXAMPLE );
186
+ })
187
+ .build ())
188
+ .toPact ();
189
+ }
190
+
191
+ @ Disabled ("https://github.com/pact-foundation/pact-jvm/issues/668" )
192
+ @ Test
193
+ void upload_code_artifact_with_metadata (final MockServer server ) throws IOException {
194
+ System .out .println ("running metadata test" );
195
+ final ContrastSDK contrast =
196
+ new ContrastSDK .Builder ("test-user" , "test-service-key" , "test-api-key" )
197
+ .withApiUrl (server .getUrl ())
198
+ .build ();
199
+ final Gson gson = GsonFactory .create ();
200
+ CodeArtifactClient client = new CodeArtifactClientImpl (contrast , gson , "organization-id" );
201
+ final CodeArtifactInner codeArtifact = client .upload ("project-id" , jar , metadataJson );
119
202
120
203
final CodeArtifactInner expected =
121
204
CodeArtifactInner .builder ()
122
205
.id ("code-artifact-id" )
123
206
.projectId ("project-id" )
124
207
.organizationId ("organization-id" )
125
208
.filename (jar .getFileName ().toString ())
209
+ .metadata (metadataJson .getFileName ().toString ())
126
210
.createdTime (TestDataConstants .TIMESTAMP_EXAMPLE )
127
211
.build ();
128
212
assertThat (codeArtifact ).isEqualTo (expected );
0 commit comments