55import com .marklogic .hub .HubConfig ;
66import org .junit .jupiter .api .Test ;
77
8- import java .io .File ;
9- import java .io .FileInputStream ;
10- import java .io .FileOutputStream ;
11- import java .io .IOException ;
12- import java .io .InputStream ;
13- import java .util .ArrayList ;
14- import java .util .Collections ;
15- import java .util .HashSet ;
16- import java .util .List ;
17- import java .util .Properties ;
18- import java .util .Set ;
8+ import java .io .*;
9+ import java .util .*;
1910import java .util .stream .Stream ;
2011import java .util .zip .ZipEntry ;
12+ import java .util .zip .ZipException ;
2113import java .util .zip .ZipFile ;
2214import java .util .zip .ZipInputStream ;
2315
@@ -36,11 +28,18 @@ public class GetProjectAsZipTest extends AbstractHubCoreTest {
3628 @ Test
3729 void forbiddenUser () {
3830 runAsTestUserWithRoles ("data-hub-operator" );
39- verifyTestUserIsForbiddenTo (()->writeProjectToZipFile (getHubClient ()), "A user must have the data-hub-download-project-files privilege" );
31+ verifyTestUserIsForbiddenTo (() -> {
32+ try {
33+ writeProjectToZipFile (getHubClient ());
34+ } catch (IOException ex ) {
35+ throw new RuntimeException (ex );
36+ }
37+ },
38+ "A user must have the data-hub-download-project-files privilege"
39+ );
4040 }
4141
4242 /**
43- *
4443 * @throws IOException
4544 */
4645 @ Test
@@ -52,7 +51,7 @@ void permittedUser() throws IOException {
5251 // Download the project, verify the zip is correct
5352 runAsTestUserWithRoles ("hub-central-downloader" );
5453
55- writeProjectToZipFile (getHubClient ());
54+ writeProjectToZipFileWithRetry (getHubClient ());
5655 verifyZipProject ();
5756 project .verifyZipArtifacts ();
5857
@@ -66,7 +65,7 @@ void permittedUser() throws IOException {
6665
6766 // Verify that downloading returns a zip without artifacts, since the database was cleared of user files
6867 runAsTestUser ();
69- writeProjectToZipFile (getHubClient ());
68+ writeProjectToZipFileWithRetry (getHubClient ());
7069 verifyZipProject ();
7170 assertEquals (0 , project .getHubCentralFilesZipEntries ().size (), "The zip should be empty since the project was reset, and thus there are " +
7271 "no user artifacts to download; zipEntries: " + new AllArtifactsProject (getHubClient ()).getHubCentralFilesZipEntries ());
@@ -76,24 +75,43 @@ void permittedUser() throws IOException {
7675 installUserArtifacts ();
7776
7877 runAsTestUser ();
79- writeProjectToZipFile (getHubClient ());
78+ writeProjectToZipFileWithRetry (getHubClient ());
8079 verifyZipProject ();
8180 project .verifyZipArtifacts ();
8281 }
8382
84- private void writeProjectToZipFile (HubClient hubClient ) {
85- try {
86- zipProjectFile = new File ("build/allProject.zip" );
87- FileOutputStream fos = new FileOutputStream (zipProjectFile );
88- new HubCentralManager ().writeProjectFilesAsZip (hubClient , fos );
89- fos .close ();
90- project = new AllArtifactsProject (getHubClient ());
91- readZipProject ();
92- project .readZipArtifacts (new ZipFile (zipProjectFile ), Collections .enumeration (artifactZipEntries ));
83+ /**
84+ * Reading the zip after it's written fails intermittently in Jenkins due to the following error:
85+ * java.util.zip.ZipException: invalid CEN header (bad signature)
86+ * It may be a bug in Java; thus, this method will try multiple times.
87+ *
88+ * @param hubClient
89+ */
90+ private void writeProjectToZipFileWithRetry (HubClient hubClient ) {
91+ final int retryLimit = 10 ;
92+ int attempt = 1 ;
93+ do {
94+ try {
95+ logger .info ("Attempting to write project to and read project from zip file; attempt: " + attempt );
96+ writeProjectToZipFile (hubClient );
97+ attempt = retryLimit + 1 ;
98+ } catch (ZipException ex ) {
99+ logger .warn ("Caught ZipException: " + ex + "; retrying, attempt: " + attempt );
100+ attempt ++;
101+ } catch (IOException ex ) {
102+ throw new RuntimeException ("Unexpected IOException: " + ex .getMessage (), ex );
103+ }
104+ } while (attempt <= retryLimit );
105+ }
93106
94- } catch (IOException e ) {
95- throw new RuntimeException (e );
107+ private void writeProjectToZipFile (HubClient hubClient ) throws IOException {
108+ zipProjectFile = new File ("build/allProject.zip" );
109+ try (FileOutputStream fos = new FileOutputStream (zipProjectFile )) {
110+ new HubCentralManager ().writeProjectFilesAsZip (hubClient , fos );
96111 }
112+ project = new AllArtifactsProject (getHubClient ());
113+ readZipProject ();
114+ project .readZipArtifacts (new ZipFile (zipProjectFile ), Collections .enumeration (artifactZipEntries ));
97115 }
98116
99117 private void readZipProject () throws IOException {
@@ -104,21 +122,20 @@ private void readZipProject() throws IOException {
104122 String [] artifactDirs = {"flows" , "steps" , "entities" , "src/main/entity-config" , "src/main/ml-config/security/protected-paths" ,
105123 "src/main/ml-config/security/query-rolesets" };
106124
107- try (ZipInputStream zipIn = new ZipInputStream (new FileInputStream (zipProjectFile ))){
125+ try (ZipInputStream zipIn = new ZipInputStream (new FileInputStream (zipProjectFile ))) {
108126 ZipEntry entry = zipIn .getNextEntry ();
109127 while (entry != null ) {
110- if ("gradle.properties" .equals (entry .getName ())){
128+ if ("gradle.properties" .equals (entry .getName ())) {
111129 InputStream input = zip .getInputStream (entry );
112130 gradleProps .load (input );
113131 }
114- if ("gradle-dhs.properties" .equals (entry .getName ())){
132+ if ("gradle-dhs.properties" .equals (entry .getName ())) {
115133 InputStream input = zip .getInputStream (entry );
116134 gradleDhsProps .load (input );
117135 }
118- if (Stream .of (artifactDirs ).anyMatch (entry .getName ()::startsWith ) && !entry .isDirectory ()){
136+ if (Stream .of (artifactDirs ).anyMatch (entry .getName ()::startsWith ) && !entry .isDirectory ()) {
119137 artifactZipEntries .add (entry );
120- }
121- else {
138+ } else {
122139 zipProjectEntries .add (entry .getName ());
123140 }
124141 zipIn .closeEntry ();
@@ -127,7 +144,7 @@ private void readZipProject() throws IOException {
127144 }
128145 }
129146
130- public void verifyZipProject (){
147+ public void verifyZipProject () {
131148 assertEquals (HubConfig .DEFAULT_STAGING_NAME , gradleProps .getProperty ("mlStagingDbName" ));
132149 assertEquals (String .valueOf (HubConfig .DEFAULT_FINAL_PORT ), gradleProps .getProperty ("mlFinalPort" ));
133150 assertEquals (HubConfig .DEFAULT_JOB_NAME , gradleProps .getProperty ("mlJobAppserverName" ));
0 commit comments