From ffaaed1868105c951eb499d4dd6555d73ab50983 Mon Sep 17 00:00:00 2001 From: ant Date: Thu, 3 Dec 2015 09:20:00 +0000 Subject: [PATCH] cli-client updates for find and delete enhancements --- cli-client/findbugs.exclude.xml | 11 + .../lars/upload/cli/FindAndDeleteFatTest.java | 263 ++++++++++++++++ .../ibm/ws/lars/upload/cli/FindFatTest.java | 289 ++++++++++++++++++ .../lars/upload/cli/ListAndDeleteFatTest.java | 3 + .../com/ibm/ws/lars/upload/cli/Action.java | 33 ++ .../java/com/ibm/ws/lars/upload/cli/Main.java | 111 +++++-- .../com/ibm/ws/lars/upload/cli/Option.java | 9 +- .../ibm/ws/lars/upload/cli/DeleteTest.java | 240 ++++++++++++++- .../com/ibm/ws/lars/upload/cli/FindTest.java | 181 +++++++++++ .../ibm/ws/lars/upload/cli/ListAllTest.java | 5 +- .../com/ibm/ws/lars/upload/cli/MainTest.java | 19 +- .../ibm/ws/lars/upload/cli/UploadTest.java | 27 +- .../ibm/ws/lars/testutils/TestProcess.java | 20 ++ 13 files changed, 1164 insertions(+), 47 deletions(-) create mode 100644 cli-client/findbugs.exclude.xml create mode 100644 cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindAndDeleteFatTest.java create mode 100644 cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindFatTest.java create mode 100644 cli-client/src/test/java/com/ibm/ws/lars/upload/cli/FindTest.java diff --git a/cli-client/findbugs.exclude.xml b/cli-client/findbugs.exclude.xml new file mode 100644 index 0000000..5ca5584 --- /dev/null +++ b/cli-client/findbugs.exclude.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindAndDeleteFatTest.java b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindAndDeleteFatTest.java new file mode 100644 index 0000000..75da085 --- /dev/null +++ b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindAndDeleteFatTest.java @@ -0,0 +1,263 @@ +/******************************************************************************* + * Copyright (c) 2015 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package com.ibm.ws.lars.upload.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.ibm.ws.lars.testutils.FatUtils; +import com.ibm.ws.lars.testutils.TestProcess; +import com.ibm.ws.lars.testutils.fixtures.RepositoryFixture; +import com.ibm.ws.repository.connections.RepositoryConnectionList; +import com.ibm.ws.repository.connections.RestRepositoryConnection; +import com.ibm.ws.repository.exceptions.RepositoryBackendException; + +/** + * Test the find actions of the command line client + */ +public class FindAndDeleteFatTest { + + @Rule + public RepositoryFixture repoServer = FatUtils.FAT_REPO; + + private RestRepositoryConnection repoConnection; + + @Before + public void setUp() { + repoConnection = (RestRepositoryConnection) repoServer.getAdminConnection(); + } + + @Test + public void testDelete() throws IOException, RepositoryBackendException { + RepositoryConnectionList connectionList = new RepositoryConnectionList(repoConnection); + + String esaPath = "resources/com.ibm.websphere.appserver.adminCenter-1.0.esa"; + TestProcess tp = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword(), + esaPath)); + tp.run(); + tp.assertReturnCode(0); + assertEquals("Incorrect resource count", 1, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 1, connectionList.getAllFeatures().size()); + tp.assertOutputContains("done"); + + // Add another asset + String esa2Path = "resources/userFeature.esa"; + TestProcess upload2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, esa2Path, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + upload2.run(); + upload2.assertReturnCode(0); + assertEquals("Incorrect resource count", 2, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 2, connectionList.getAllFeatures().size()); + upload2.assertOutputContains("done"); + + // List assets, should now show 2 assets + TestProcess list2Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "listAll", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + list2Process.run(); + String list2output = list2Process.getOutput(); + int lineCount2 = FatUtils.countLines(list2output); + + assertEquals("Output had the wrong number of lines\n" + list2output, 4, lineCount2); + findFeatureId(list2output, "Admin Center"); + list2Process.assertReturnCode(0); + + // Delete asset + TestProcess deleteProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "findAndDelete", + "--noPrompts", + "admin", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + deleteProcess.run(); + String deleteOutput = deleteProcess.getOutput(); + int lineCount = FatUtils.countLines(deleteOutput); + + assertEquals("Output had the wrong number of lines\n" + deleteOutput, 1, lineCount); + assertTrue("Asset not deleted\n" + deleteOutput + "\n" + list2output, deleteOutput.contains("Deleted asset ")); + deleteProcess.assertReturnCode(0); + + // List assets, should now show 1 assets + TestProcess list3Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "listAll", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + list3Process.run(); + String list3output = list3Process.getOutput(); + int lineCount3 = FatUtils.countLines(list3output); + + assertEquals("Output had the wrong number of lines\n" + list3output, 3, lineCount3); + findFeatureId(list3output, "com.ibm.ws.test.userFeature"); + list3Process.assertReturnCode(0); + + } + + @Test + public void testDeleteWithPrompts() throws IOException, RepositoryBackendException { + RepositoryConnectionList connectionList = new RepositoryConnectionList(repoConnection); + + String esaPath = "resources/com.ibm.websphere.appserver.adminCenter-1.0.esa"; + TestProcess tp = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword(), + esaPath)); + tp.run(); + tp.assertReturnCode(0); + assertEquals("Incorrect resource count", 1, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 1, connectionList.getAllFeatures().size()); + tp.assertOutputContains("done"); + + // Add another asset + String esa2Path = "resources/userFeature.esa"; + TestProcess upload2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, esa2Path, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + upload2.run(); + upload2.assertReturnCode(0); + assertEquals("Incorrect resource count", 2, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 2, connectionList.getAllFeatures().size()); + upload2.assertOutputContains("done"); + + // List assets, should now show 2 assets + TestProcess list2Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "listAll", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + list2Process.run(); + String list2output = list2Process.getOutput(); + int lineCount2 = FatUtils.countLines(list2output); + + assertEquals("Output had the wrong number of lines\n" + list2output, 4, lineCount2); + findFeatureId(list2output, "Admin Center"); + list2Process.assertReturnCode(0); + + // Delete asset but answer "n" to the deletion prompt + TestProcess deleteProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "findAndDelete", + "admin", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword()), "n" + System.lineSeparator()); + + deleteProcess.run(); + + String deleteOutput = deleteProcess.getOutput(); + int lineCount = FatUtils.countLines(deleteOutput); + + assertEquals("Output had the wrong number of lines\n" + deleteOutput, 1, lineCount); + assertTrue("No delete prompt\n" + deleteOutput + "\n" + list2output, deleteOutput.contains("Delete asset ")); + deleteProcess.assertReturnCode(0); + + // List assets, should still show 2 assets + TestProcess list3Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "listAll", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + list3Process.run(); + String list3output = list3Process.getOutput(); + int lineCount3 = FatUtils.countLines(list3output); + + assertEquals("Output had the wrong number of lines\n" + list3output, 4, lineCount3); + findFeatureId(list3output, "com.ibm.ws.test.userFeature"); + findFeatureId(list2output, "Admin Center"); + list3Process.assertReturnCode(0); + + // Delete asset answering "y" to the deletion prompt + TestProcess deleteProcess2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "findAndDelete", + "admin", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword()), "y" + System.lineSeparator()); + + deleteProcess2.run(); + + String delete2Output = deleteProcess2.getOutput(); + int lineCount4 = FatUtils.countLines(delete2Output); + + assertEquals("Output had the wrong number of lines\n" + delete2Output, 2, lineCount4); + assertTrue("No delete prompt\n" + delete2Output + "\n" + delete2Output, delete2Output.contains("Delete asset ")); + assertTrue("Asset not deleted\n" + delete2Output + "\n" + delete2Output, delete2Output.contains("Deleted asset ")); + deleteProcess.assertReturnCode(0); + + // List assets, should now show 1 asset + TestProcess list4Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "listAll", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + list4Process.run(); + String list4output = list4Process.getOutput(); + int lineCount5 = FatUtils.countLines(list4output); + + assertEquals("Output had the wrong number of lines\n" + list4output, 3, lineCount5); + findFeatureId(list3output, "com.ibm.ws.test.userFeature"); + list3Process.assertReturnCode(0); + } + + /** + * Finds the id of a feature from the output of the list command, or fails the test if it can't + * be found. Output from the list command looks something like: + * + * Listing all assets in the repository:
+ * Asset ID | Asset Type | Liberty Version | Asset Name
+ * 54be3a90469ba2513fea88e7 | Feature | 8.5.5.5 | Admin Center (adminCenter-1.0) + * + * where the version may be blank + * + * @param output - output of the list command + * @param name - name of the feature to find + * @return + */ + private static String findFeatureId(String output, String name) { + + String regex = "(\\w+)\\s+\\|\\s+Feature\\s+\\|.+\\|\\s+" + name; + Pattern idPattern = Pattern.compile(regex); + Matcher idMatcher = idPattern.matcher(output); + boolean result = idMatcher.find(); + assertTrue("Can't find id for feature " + name + " in output:\n" + output, result); + String id = idMatcher.group(1); + return id; + } + +} diff --git a/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindFatTest.java b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindFatTest.java new file mode 100644 index 0000000..8e3b1eb --- /dev/null +++ b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/FindFatTest.java @@ -0,0 +1,289 @@ +/******************************************************************************* + * Copyright (c) 2015 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package com.ibm.ws.lars.upload.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.ibm.ws.lars.testutils.FatUtils; +import com.ibm.ws.lars.testutils.TestProcess; +import com.ibm.ws.lars.testutils.fixtures.RepositoryFixture; +import com.ibm.ws.repository.common.enums.LicenseType; +import com.ibm.ws.repository.common.enums.State; +import com.ibm.ws.repository.connections.RepositoryConnectionList; +import com.ibm.ws.repository.connections.RestRepositoryConnection; +import com.ibm.ws.repository.exceptions.RepositoryBackendException; +import com.ibm.ws.repository.resources.EsaResource; +import com.ibm.ws.repository.resources.writeable.EsaResourceWritable; + +/** + * Test the find actions of the command line client + */ +public class FindFatTest { + + @Rule + public RepositoryFixture repoServer = FatUtils.FAT_REPO; + + private RestRepositoryConnection repoConnection; + + @Before + public void setUp() { + repoConnection = (RestRepositoryConnection) repoServer.getAdminConnection(); + } + + @Test + public void testFind() throws IOException, RepositoryBackendException { + RepositoryConnectionList connectionList = new RepositoryConnectionList(repoConnection); + + String esaPath = "resources/com.ibm.websphere.appserver.adminCenter-1.0.esa"; + File esaFile = new File(esaPath); + TestProcess tp = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword(), + esaPath)); + tp.run(); + tp.assertReturnCode(0); + assertEquals("Incorrect resource count", 1, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 1, connectionList.getAllFeatures().size()); + tp.assertOutputContains("done"); + + EsaResource resource = connectionList.getAllFeatures().iterator().next(); + assertEquals("Incorrect state", State.PUBLISHED, ((EsaResourceWritable) resource).getState()); + assertEquals("Incorrect license type", LicenseType.UNSPECIFIED, resource.getLicenseType()); + assertEquals("Incorrect size", esaFile.length(), resource.getMainAttachmentSize()); + + // Find assets, should show just the uploaded above + TestProcess findProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + findProcess.run(); + String output = findProcess.getOutput(); + + assertFalse(output, output.contains("No assets found in repository")); + assertTrue("More than one feature found: " + output, (output.indexOf("Feature") == output.lastIndexOf("Feature") && output.indexOf("Feature") != -1)); + int lineCount = FatUtils.countLines(output); + assertEquals("Output had the wrong number of lines\n" + output, 2, lineCount); + findFeatureId(output, "Admin Center"); + findProcess.assertReturnCode(0); + + // Add another asset + String esa2Path = "resources/userFeature.esa"; + TestProcess upload2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, esa2Path, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + upload2.run(); + upload2.assertReturnCode(0); + assertEquals("Incorrect resource count", 2, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 2, connectionList.getAllFeatures().size()); + upload2.assertOutputContains("done"); + + // List assets, should now show 2 assets + TestProcess find2Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + find2Process.run(); + String list2output = find2Process.getOutput(); + int lineCount2 = FatUtils.countLines(list2output); + assertEquals("Output had the wrong number of lines\n" + list2output, 3, lineCount2); + findFeatureId(list2output, "Admin Center"); + find2Process.assertReturnCode(0); + } + + @Test + public void testFindWithName() throws IOException, RepositoryBackendException { + RepositoryConnectionList connectionList = new RepositoryConnectionList(repoConnection); + + String esaPath = "resources/com.ibm.websphere.appserver.adminCenter-1.0.esa"; + TestProcess tp = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword(), + esaPath)); + tp.run(); + tp.assertReturnCode(0); + assertEquals("Incorrect resource count", 1, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 1, connectionList.getAllFeatures().size()); + tp.assertOutputContains("done"); + + // Add another asset + String esa2Path = "resources/userFeature.esa"; + TestProcess upload2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, esa2Path, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + upload2.run(); + upload2.assertReturnCode(0); + upload2.assertOutputContains("done"); + + // should now be two assets + assertEquals("Incorrect resource count", 2, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 2, connectionList.getAllFeatures().size()); + + // Find assets, should show the two uploaded above + TestProcess findProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + findProcess.run(); + String output = findProcess.getOutput(); + + assertFalse(output, output.contains("No assets found in repository")); + int lineCount = FatUtils.countLines(output); + assertEquals("Output had the wrong number of lines\n" + output, 3, lineCount); + findProcess.assertReturnCode(0); + + // Fine with name, should now show just the one asset + TestProcess find2Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "", + "--name=Admin Center", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + find2Process.run(); + String list2output = find2Process.getOutput(); + int lineCount2 = FatUtils.countLines(list2output); + + assertEquals("Output had the wrong number of lines\n" + list2output, 2, lineCount2); + assertTrue("More than one feature found: " + list2output, (list2output.indexOf("Feature") == list2output.lastIndexOf("Feature") && list2output.indexOf("Feature") != -1)); + findFeatureId(list2output, "Admin Center"); + find2Process.assertReturnCode(0); + } + + @Test + public void testFindSearchtSring() throws IOException, RepositoryBackendException { + RepositoryConnectionList connectionList = new RepositoryConnectionList(repoConnection); + + String esaPath = "resources/com.ibm.websphere.appserver.adminCenter-1.0.esa"; + File esaFile = new File(esaPath); + TestProcess tp = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword(), + esaPath)); + tp.run(); + tp.assertReturnCode(0); + assertEquals("Incorrect resource count", 1, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 1, connectionList.getAllFeatures().size()); + tp.assertOutputContains("done"); + + EsaResource resource = connectionList.getAllFeatures().iterator().next(); + assertEquals("Incorrect state", State.PUBLISHED, ((EsaResourceWritable) resource).getState()); + assertEquals("Incorrect license type", LicenseType.UNSPECIFIED, resource.getLicenseType()); + assertEquals("Incorrect size", esaFile.length(), resource.getMainAttachmentSize()); + + // Find assets, should show just the uploaded above + TestProcess findProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "admin", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + findProcess.run(); + String output = findProcess.getOutput(); + + assertFalse(output, output.contains("No assets found in repository")); + assertTrue("More than one feature found: " + output, (output.indexOf("Feature") == output.lastIndexOf("Feature") && output.indexOf("Feature") != -1)); + int lineCount = FatUtils.countLines(output); + assertEquals("Output had the wrong number of lines\n" + output, 2, lineCount); + findFeatureId(output, "Admin Center"); + findProcess.assertReturnCode(0); + + // Add another asset + String esa2Path = "resources/userFeature.esa"; + TestProcess upload2 = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "upload", + "--url=" + FatUtils.SERVER_URL, esa2Path, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + upload2.run(); + upload2.assertReturnCode(0); + assertEquals("Incorrect resource count", 2, connectionList.getAllResources().size()); + assertEquals("Incorrect feature count", 2, connectionList.getAllFeatures().size()); + upload2.assertOutputContains("done"); + + // List assets, should now show 2 assets + TestProcess find2Process = new TestProcess(Arrays.asList(FatUtils.SCRIPT, + "find", + "admin", + "--url=" + FatUtils.SERVER_URL, + "--username=" + repoConnection.getUserId(), + "--password=" + repoConnection.getPassword())); + find2Process.run(); + String list2output = find2Process.getOutput(); + int lineCount2 = FatUtils.countLines(list2output); + + assertEquals("Output had the wrong number of lines\n" + list2output, 2, lineCount2); + assertTrue("More than one feature found: " + output, (output.indexOf("Feature") == output.lastIndexOf("Feature") && output.indexOf("Feature") != -1)); + lineCount = FatUtils.countLines(output); + assertEquals("Output had the wrong number of lines\n" + output, 2, lineCount); + findFeatureId(output, "Admin Center"); + find2Process.assertReturnCode(0); + } + + /** + * Finds the id of a feature from the output of the list command, or fails the test if it can't + * be found. Output from the list command looks something like: + * + * Listing all assets in the repository:
+ * Asset ID | Asset Type | Liberty Version | Asset Name
+ * 54be3a90469ba2513fea88e7 | Feature | 8.5.5.5 | Admin Center (adminCenter-1.0) + * + * where the version may be blank + * + * @param output - output of the list command + * @param name - name of the feature to find + * @return + */ + private static String findFeatureId(String output, String name) { + + String regex = "(\\w+)\\s+\\|\\s+Feature\\s+\\|.+\\|\\s+" + name; + Pattern idPattern = Pattern.compile(regex); + Matcher idMatcher = idPattern.matcher(output); + boolean result = idMatcher.find(); + assertTrue("Can't find id for feature " + name + " in output:\n" + output, result); + String id = idMatcher.group(1); + return id; + } + +} diff --git a/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/ListAndDeleteFatTest.java b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/ListAndDeleteFatTest.java index 5021747..2096f36 100644 --- a/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/ListAndDeleteFatTest.java +++ b/cli-client/src/fat/java/com/ibm/ws/lars/upload/cli/ListAndDeleteFatTest.java @@ -122,6 +122,7 @@ public void testDelete() throws IOException, RepositoryBackendException { // Delete both assets TestProcess deleteProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, "delete", + "--noPrompts", "--url=" + FatUtils.SERVER_URL, "--username=" + repoConnection.getUserId(), "--password=" + repoConnection.getPassword(), @@ -135,6 +136,7 @@ public void testDelete() throws IOException, RepositoryBackendException { // Delete again and check that it fails TestProcess deleteAgain = new TestProcess(Arrays.asList(FatUtils.SCRIPT, "delete", + "--noPrompts", "--url=" + FatUtils.SERVER_URL, "--username=" + repoConnection.getUserId(), "--password=" + repoConnection.getPassword(), @@ -149,6 +151,7 @@ public void testDelete() throws IOException, RepositoryBackendException { public void testDeleteInvalidUrl() throws IOException { TestProcess deleteProcess = new TestProcess(Arrays.asList(FatUtils.SCRIPT, "delete", + "--noPrompts", "--url=" + "invalidurl", "--username=" + repoConnection.getUserId(), "--password=" + repoConnection.getPassword(), diff --git a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Action.java b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Action.java index fdf7a5a..6a64d5c 100644 --- a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Action.java +++ b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Action.java @@ -56,6 +56,22 @@ public String getHelpDetail() { + "Note that subdirectories are not recursively searched."; } }, + FIND("find") { + @Override + public String getHelpSummary() { + return "Find assets in the repository."; + } + + @Override + public String getUsage() { + return "find [--name=] searchString"; + } + + @Override + public String getHelpDetail() { + return "Finds all the assets in the repository that match the values of the name and searchString arguments."; + } + }, DELETE("delete") { @Override public String getHelpSummary() { @@ -72,6 +88,23 @@ public String getHelpDetail() { return "Delete one or more assets from the repository, specified by id."; } }, + FIND_AND_DELETE("findAndDelete") { + @Override + public String getHelpSummary() { + return "Find and delete assets in the repository."; + } + + @Override + public String getUsage() { + return "findAndDelete [--noPrompts] [--name=] searchString"; + } + + @Override + public String getHelpDetail() { + return "Finds and deletes all the assets in the repository that match the values of the name and searchString arguments. The --name must be an exact match. " + + "Unless the noPrompts option is specified each asset deletion will prompt for confirmation before being deleted."; + } + }, LISTALL("listAll") { @Override public String getHelpSummary() { diff --git a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Main.java b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Main.java index f3db9aa..987ef10 100644 --- a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Main.java +++ b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Main.java @@ -16,12 +16,14 @@ package com.ibm.ws.lars.upload.cli; +import java.io.BufferedReader; import java.io.Console; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; @@ -30,6 +32,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; @@ -66,6 +69,7 @@ public class Main { private Map options; private Action action; + private final InputStream input; private final PrintStream output; /** Filter that only accepts .esa files */ @@ -76,9 +80,7 @@ public boolean accept(File file) { return false; String name = file.getName(); - return !file.isDirectory() && - name != null && - name.endsWith(".esa"); + return !file.isDirectory() && name != null && name.endsWith(".esa"); } }; @@ -86,7 +88,7 @@ public boolean accept(File file) { * All logic here should be delegated to run, to allow for easier testing */ public static void main(String[] args) { - Main main = new Main(System.out); + Main main = new Main(System.in, System.out); try { main.run(args); @@ -97,8 +99,9 @@ public static void main(String[] args) { System.exit(0); } - public Main(PrintStream output) { - this.output = output; + public Main(InputStream in, PrintStream out) { + this.input = in; + this.output = out; } /** @@ -119,6 +122,13 @@ public void run(String[] args) throws ClientException { case DELETE: doDelete(remainingArgs); break; + case FIND: + doFind(remainingArgs); + break; + case FIND_AND_DELETE: + // doDelete has conditional code checking for the FIND_AND_DELETE action + doDelete(remainingArgs); + break; case LISTALL: doListAll(remainingArgs); break; @@ -193,8 +203,7 @@ private List readActionAndOptions(String[] args) throws ClientException if (keepProcessingOptions && arg.equals("--")) { keepProcessingOptions = false; - } - else if (keepProcessingOptions && arg.startsWith("--")) { + } else if (keepProcessingOptions && arg.startsWith("--")) { String[] argParts = arg.substring(2).split("=", 2); if (argParts.length == 0) { throw new ClientException(arg + " is not a valid option", 1, HelpDisplay.SHOW_HELP); @@ -208,8 +217,7 @@ else if (keepProcessingOptions && arg.startsWith("--")) { } options.put(option, value); - } - else { + } else { nonOptionArgs.add(arg); } } @@ -236,6 +244,8 @@ private void showHelp(List remainingArgs) { case UPLOAD: case DELETE: case LISTALL: + case FIND: + case FIND_AND_DELETE: help.printCommandUsage(action.getUsage(), action.getHelpDetail()); help.printGlobalOptions(); break; @@ -294,8 +304,7 @@ private void doUpload(List remainingArgs) throws ClientException { try { uploader = new MassiveEsa(repoConnection); } catch (RepositoryException ex) { - throw new ClientException("An error occurred while connecting to the repository: " + ex.getMessage(), - 1, HelpDisplay.NO_HELP, ex); + throw new ClientException("An error occurred while connecting to the repository: " + ex.getMessage(), 1, HelpDisplay.NO_HELP, ex); } int size = files.size(); @@ -323,8 +332,7 @@ private void doUpload(List remainingArgs) throws ClientException { output.println("done"); } } catch (RepositoryException ex) { - throw new ClientException("An error occurred while uploading " + file.toString() + ": " + ex.getMessage(), - 1, HelpDisplay.NO_HELP, ex); + throw new ClientException("An error occurred while uploading " + file.toString() + ": " + ex.getMessage(), 1, HelpDisplay.NO_HELP, ex); } } } @@ -341,6 +349,14 @@ private void doListAll(List params) throws ClientException { output.println("Listing all assets in the repository:"); + printAssets(assets); + + } + + /** + * @param assets + */ + private void printAssets(Collection assets) { if (assets.size() == 0) { output.println("No assets found in repository"); return; @@ -377,20 +393,63 @@ private void doListAll(List params) throws ClientException { printTabbed(resource.getId(), type, appliesTo, name); } - } void printTabbed(String id, String type, String appliesTo, String name) { output.format("%-30.30s | %-15.15s | %-15.15s | %s%n", id, type, appliesTo, name); } + private List doFind(List remainingArgs) throws ClientException { + + RepositoryConnection repoConnection = createRepoConnection(); + Collection assets = null; + try { + if (remainingArgs.size() > 0) { + String searchString = remainingArgs.get(0); + assets = repoConnection.findResources(searchString, null, null, null); + } else { + assets = repoConnection.getAllResources(); + } + } catch (RepositoryBackendException e) { + throw new ClientException("An error was recieved from the repository: " + e.getMessage(), 1, HelpDisplay.NO_HELP, e); + } + + if (options.containsKey(Option.NAME)) { + String name = options.get(Option.NAME); + Iterator i = assets.iterator(); + while (i.hasNext()) { + String assetName = i.next().getName(); + if (assetName == null || !!!assetName.contains(name)) { + i.remove(); + } + } + } + + if (action == Action.FIND_AND_DELETE) { + List assetIds = new ArrayList(assets.size()); + for (RepositoryResource resource : assets) { + assetIds.add(resource.getId()); + } + return assetIds; + } + + printAssets(assets); + return null; + } + private void doDelete(List remainingArgs) throws ClientException { RepositoryConnection repoConnection = createRepoConnection(); - if (remainingArgs.size() == 0) { + if (remainingArgs.size() == 0 && !!!options.containsKey(Option.FIND_DELETE)) { throw new ClientException(NO_IDS_FOR_DELETE, 1, HelpDisplay.SHOW_HELP); } + if (action == Action.FIND_AND_DELETE) { + remainingArgs = doFind(remainingArgs); + } + + BufferedReader inputReader = new BufferedReader(new InputStreamReader(input)); + for (String id : remainingArgs) { RepositoryResourceWritable toDelete = null; try { @@ -408,13 +467,22 @@ private void doDelete(List remainingArgs) throws ClientException { continue; } // Anything else should be a server error - throw new ClientException("Asset " + id + " not deleted. " + SERVER_ERROR + e.getMessage(), - 1, HelpDisplay.NO_HELP, e); + throw new ClientException("Asset " + id + " not deleted. " + SERVER_ERROR + e.getMessage(), 1, HelpDisplay.NO_HELP, e); } catch (RepositoryBackendException e) { // Anything else is probably some kind of connection problem, so ditch out - throw new ClientException("Asset " + id + " not deleted. " + CONNECTION_PROBLEM + e.getMessage(), - 1, HelpDisplay.NO_HELP, e); + throw new ClientException("Asset " + id + " not deleted. " + CONNECTION_PROBLEM + e.getMessage(), 1, HelpDisplay.NO_HELP, e); + } + + if ((action == Action.FIND_AND_DELETE) && !!!options.containsKey(Option.NO_PROMPTS)) { + output.println("Delete asset " + toDelete.getId() + " " + toDelete.getName() + " (y/N)?"); + try { + if (!!!("y".equalsIgnoreCase(inputReader.readLine()))) { + continue; + } + } catch (IOException e) { + throw new ClientException(e.getMessage(), 1, HelpDisplay.NO_HELP, e); + } } try { @@ -484,8 +552,7 @@ private RepositoryConnection createRepoConnection() throws ClientException { } if (username == null && (password != null || promptForPassword)) { - throw new ClientException("A username must be provided if a password is provided or will be prompted for", - 1, HelpDisplay.SHOW_HELP); + throw new ClientException("A username must be provided if a password is provided or will be prompted for", 1, HelpDisplay.SHOW_HELP); } if (promptForPassword) { diff --git a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Option.java b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Option.java index c747fb1..b84f9f4 100644 --- a/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Option.java +++ b/cli-client/src/main/java/com/ibm/ws/lars/upload/cli/Option.java @@ -23,7 +23,14 @@ public enum Option { URL("url"), USERNAME("username"), PASSWORD("password"), - CONFIG_FILE("configFile"); + CONFIG_FILE("configFile"), + + // options for the find command + FIND_DELETE("F"), + NAME("name"), + + // options for the delete command + NO_PROMPTS("noPrompts"); private String argument; diff --git a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/DeleteTest.java b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/DeleteTest.java index 4644d55..7ec46fa 100644 --- a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/DeleteTest.java +++ b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/DeleteTest.java @@ -17,20 +17,26 @@ package com.ibm.ws.lars.upload.cli; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; - -import mockit.Mock; -import mockit.MockUp; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import org.junit.After; import org.junit.Test; +import com.ibm.ws.repository.common.enums.ResourceType; +import com.ibm.ws.repository.common.enums.Visibility; +import com.ibm.ws.repository.connections.ProductDefinition; import com.ibm.ws.repository.connections.RestRepositoryConnection; import com.ibm.ws.repository.exceptions.RepositoryBackendException; import com.ibm.ws.repository.exceptions.RepositoryBackendIOException; @@ -41,11 +47,15 @@ import com.ibm.ws.repository.resources.internal.EsaResourceImpl; import com.ibm.ws.repository.transport.exceptions.RequestFailureException; +import mockit.Mock; +import mockit.MockUp; + public class DeleteTest { private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); private final PrintStream output = new PrintStream(baos); - private final Main tested = new Main(output); + private InputStream input = new ByteArrayInputStream(new byte[0]); + private Main tested = new Main(input, output); @After public void tearDown() { @@ -175,7 +185,7 @@ public RepositoryResource getResource(String id) throws RepositoryBackendExcepti }; try { - tested.run(new String[] { "--delete", "--url=http://localhost:9080", "9999" }); + tested.run(new String[] { "--delete", "--noPrompts", "--url=http://localhost:9080", "9999" }); } catch (ClientException e) { String output = baos.toString(); @@ -237,7 +247,7 @@ public void delete() throws RepositoryResourceDeletionException { }; try { - tested.run(new String[] { "--delete", "--url=http://localhost:9080", "9999" }); + tested.run(new String[] { "--delete", "--noPrompts", "--url=http://localhost:9080", "9999" }); } catch (ClientException e) { String output = baos.toString(); @@ -250,4 +260,222 @@ public void delete() throws RepositoryResourceDeletionException { } + @Test + public void testFindAndDelete() throws ClientException { + + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + return; + } + }; + List rs = Arrays.asList(new RepositoryResource[] { deleteable }); + return rs; + } + + @Mock + public RepositoryResource getResource(String id) throws RepositoryBackendException, RepositoryBadDataException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + return deleteable; + } + }; + + DeleteTest.this.deleteCalled = false; + tested.run(new String[] { "--findAndDelete", "--noPrompts", "--url=http://localhost:9080", "admin" }); + + String output = baos.toString(); + + assertTrue("Expected message was missing. Output was:\n" + output, output.contains("Deleted asset null")); + assertTrue("Delete not called", deleteCalled); + } + + @Test + public void testFindAndDeletePromptN() throws ClientException { + + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + List rs = Arrays.asList(new RepositoryResource[] { deleteable }); + return rs; + } + + @Mock + public RepositoryResource getResource(String id) throws RepositoryBackendException, RepositoryBadDataException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + return deleteable; + } + }; + + String sysIn = "n" + System.lineSeparator(); + input = new ByteArrayInputStream(sysIn.getBytes()); + tested = new Main(input, output); + + DeleteTest.this.deleteCalled = false; + tested.run(new String[] { "--findAndDelete", "--url=http://localhost:9080", "admin" }); + + String output = baos.toString(); + + assertTrue("Expected message was missing. Output was:\n" + output, output.contains("Delete asset null null (y/N)?")); + assertFalse("Delete called", deleteCalled); + } + + Boolean deleteCalled = false; + + @Test + public void testFindAndDeletePromptY() throws ClientException { + deleteCalled = false; + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + List rs = Arrays.asList(new RepositoryResource[] { deleteable }); + return rs; + } + + @Mock + public RepositoryResource getResource(String id) throws RepositoryBackendException, RepositoryBadDataException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + return deleteable; + } + }; + + String sysIn = "y" + System.lineSeparator(); + input = new ByteArrayInputStream(sysIn.getBytes()); + tested = new Main(input, output); + + tested.run(new String[] { "--findAndDelete", "--url=http://localhost:9080", "admin" }); + + String output = baos.toString(); + + assertTrue("Expected message was missing. Output was:\n" + output, output.contains("Delete asset null null (y/N)?")); + assertTrue("Delete not called", deleteCalled); + } + + @Test + public void testFindAndDeletePromptNull() throws ClientException { + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + List rs = Arrays.asList(new RepositoryResource[] { deleteable }); + return rs; + } + + @Mock + public RepositoryResource getResource(String id) throws RepositoryBackendException, RepositoryBadDataException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + return deleteable; + } + }; + + deleteCalled = false; + String sysIn = System.lineSeparator(); // No input, just hit enter + input = new ByteArrayInputStream(sysIn.getBytes()); + tested = new Main(input, output); + + tested.run(new String[] { "--findAndDelete", "--url=http://localhost:9080", "admin" }); + + String output = baos.toString(); + + assertTrue("Expected message was missing. Output was:\n" + output, output.contains("Delete asset null null (y/N)?")); + assertFalse("Delete called", deleteCalled); + } + + @Test + public void testFindAndDeletePromptRandom() throws ClientException { + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + List rs = Arrays.asList(new RepositoryResource[] { deleteable }); + return rs; + } + + @Mock + public RepositoryResource getResource(String id) throws RepositoryBackendException, RepositoryBadDataException { + RepositoryResource deleteable = new EsaResourceImpl(null) { + @Override + public void delete() throws RepositoryResourceDeletionException { + DeleteTest.this.deleteCalled = true; + return; + } + }; + return deleteable; + } + }; + + deleteCalled = false; + String sysIn = "xyz" + System.lineSeparator(); + input = new ByteArrayInputStream(sysIn.getBytes()); + tested = new Main(input, output); + + tested.run(new String[] { "--findAndDelete", "--url=http://localhost:9080", "admin" }); + + String output = baos.toString(); + + assertTrue("Expected message was missing. Output was:\n" + output, output.contains("Delete asset null null (y/N)?")); + assertFalse("Delete called", deleteCalled); + } } diff --git a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/FindTest.java b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/FindTest.java new file mode 100644 index 0000000..1766392 --- /dev/null +++ b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/FindTest.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2015 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ + +package com.ibm.ws.lars.upload.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.Test; + +import com.ibm.ws.repository.common.enums.ResourceType; +import com.ibm.ws.repository.common.enums.Visibility; +import com.ibm.ws.repository.connections.ProductDefinition; +import com.ibm.ws.repository.connections.RepositoryConnection; +import com.ibm.ws.repository.exceptions.RepositoryBackendException; +import com.ibm.ws.repository.resources.EsaResource; +import com.ibm.ws.repository.resources.RepositoryResource; +import com.ibm.ws.repository.resources.internal.EsaResourceImpl; +import com.ibm.ws.repository.resources.internal.RepositoryResourceImpl; +import com.ibm.ws.repository.transport.model.Asset; +import com.ibm.ws.repository.transport.model.WlpInformation; + +import mockit.Mock; +import mockit.MockUp; + +public class FindTest { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ByteArrayOutputStream ebaos = new ByteArrayOutputStream(); + PrintStream output = new PrintStream(baos); + PrintStream errorStream = new PrintStream(ebaos); + InputStream input = new ByteArrayInputStream(new byte[0]); + Main tested = new Main(input, output); + + @After + public void tearDown() { + output.close(); + errorStream.close(); + } + + @Test + public void testNoUrl() { + + // Should throw an exception and print out a help message + + try { + tested.run(new String[] { "--find" }); + } catch (ClientException e) { + assertEquals("Unexpected exception message", Main.MISSING_URL, e.getMessage()); + String outputString = baos.toString(); + assertTrue("The expected help output wasn't produced, was:\n" + outputString, TestUtils.checkForHelpMessage(outputString)); + + String errorOutput = ebaos.toString(); + assertEquals("No output was expected to stderr", "", errorOutput); + return; + } + fail("The expected client exception was not thrown"); + } + + @Test + public void testFooUrl() { + + // Should throw an exception but no help message + + try { + tested.run(new String[] { "--find", "--url=foobar" }); + } catch (ClientException e) { + assertEquals("Unexpected exception message", Main.INVALID_URL + "foobar", e.getMessage()); + String outputString = baos.toString(); + assertTrue("The expected output wasn't produced, was:\n" + outputString, outputString.contains(Main.INVALID_URL)); + String errorOutput = ebaos.toString(); + assertEquals("No output was expected to stderr", "", errorOutput); + return; + } + fail("The expected client exception was not thrown"); + } + + @Test + public void testEmptyRepository() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, ClientException { + + new MockUp() { + @Mock + public Collection findResources(String searchTerm, Collection productDefinitions, + Collection types, + Visibility visibility) throws RepositoryBackendException { + return Collections.emptySet(); + } + }; + + tested.run(new String[] { "--find", "*", "--url=http://foobar.baz" }); + String output = baos.toString(); + assertTrue("The test output didn't contain the expected string, was: " + output, + output.contains("No assets found in repository")); + assertEquals("The error output wasn't empty", "", ebaos.toString()); + } + + @Test + public void testFind() throws ClientException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + final List getAllList = new ArrayList<>(); + getAllList.add(getTestEsa("1", "A name", "A short description", "productVersion=8.5.5.4;")); + getAllList.add(getTestEsa("2", "A name", null, null)); + getAllList.add(getTestEsa("3", "A quoted version", "A shortish description", "productVersion=\"8.5.5.7\";")); + + new MockUp() { + @Mock + public Collection getAllResources() throws RepositoryBackendException { + return getAllList; + } + }; + + tested.run(new String[] { "--find", "--url=http://foobar.baz" }); + String output = baos.toString(); + + Pattern pat = Pattern.compile("1\\s\\+|\\s+Feature\\s+\\|\\s+8\\.5\\.5\\.4\\s+\\|\\s+A name\\s+\\(A short description\\)"); + Matcher match = pat.matcher(output); + assertTrue("The output didn't contain the expected asset description:\n" + output, match.find()); + + Pattern pat2 = Pattern.compile("2\\s+\\|\\s+Feature\\s+\\|\\s+\\|\\s+A name"); + Matcher match2 = pat2.matcher(output); + assertTrue("The output didn't contain the expected asset description:\n" + output, match2.find()); + + Pattern pat3 = Pattern.compile("1\\s\\+|\\s+Feature\\s+\\|\\s+8\\.5\\.5\\.7\\s+\\|\\s+A quoted version\\s+\\(A shortish description\\)"); + Matcher match3 = pat3.matcher(output); + assertTrue("The output didn't contain the expected asset description:\n" + output, match3.find()); + + assertEquals("The error output wasn't empty", "", ebaos.toString()); + } + + /** + * Creates an EsaResource with the specified fields. These are normally created from the + * repository or read in from a real Esa, so a number of fields have to be set reflectively. + */ + private EsaResource getTestEsa(String id, String name, String shortName, + String appliesTo) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + Asset asset = new Asset(); + asset.set_id(id); + asset.setName(name); + asset.setType(ResourceType.FEATURE); + WlpInformation info = new WlpInformation(); + if (shortName != null) { + info.setShortName(shortName); + } + info.setAppliesTo(appliesTo); + asset.setWlpInformation(info); + + EsaResource er = new EsaResourceImpl(null); + Field assetField = RepositoryResourceImpl.class.getDeclaredField("_asset"); + assetField.setAccessible(true); + assetField.set(er, asset); + + return er; + } + +} diff --git a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/ListAllTest.java b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/ListAllTest.java index ee09d70..a5115e9 100644 --- a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/ListAllTest.java +++ b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/ListAllTest.java @@ -20,7 +20,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.PrintStream; import java.lang.reflect.Field; import java.util.ArrayList; @@ -52,7 +54,8 @@ public class ListAllTest { ByteArrayOutputStream ebaos = new ByteArrayOutputStream(); PrintStream output = new PrintStream(baos); PrintStream errorStream = new PrintStream(ebaos); - Main tested = new Main(output); + InputStream input = new ByteArrayInputStream(new byte[0]); + Main tested = new Main(input, output); @After public void tearDown() { diff --git a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/MainTest.java b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/MainTest.java index 46fc0e8..9908e4b 100644 --- a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/MainTest.java +++ b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/MainTest.java @@ -21,7 +21,9 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.PrintStream; import org.junit.Test; @@ -42,9 +44,10 @@ public MainRunner(String expectedExceptionMessage, int expectedStdoutLines) { } public void run(String... args) throws ClientException { + InputStream input = new ByteArrayInputStream(new byte[0]); ByteArrayOutputStream stdoutBAOS = new ByteArrayOutputStream(); try (PrintStream output = new PrintStream(stdoutBAOS)) { - Main main = new Main(output); + Main main = new Main(input, output); Exception exception = null; try { main.run(args); @@ -76,14 +79,14 @@ public void run(String... args) throws ClientException { */ @Test public void testRun() throws ClientException { - MainRunner runner = new MainRunner("No options were given", 41); + MainRunner runner = new MainRunner("No options were given", 47); runner.run(); assertThat(runner.stdout, containsString("Usage: java -jar larsClient.jar action [options] [arguments]")); } @Test public void shouldPrintHelpMessageIfHelpOptionSpecified() throws ClientException { - MainRunner runner = new MainRunner(null, 39); + MainRunner runner = new MainRunner(null, 45); runner.run("--help"); assertThat(runner.stdout, containsString("Usage: java -jar larsClient.jar action [options] [arguments] ...")); assertThat(runner.stdout, containsString("Show help for larsClient.")); @@ -95,7 +98,7 @@ public void shouldPrintHelpMessageIfHelpOptionSpecified() throws ClientException @Test public void shouldPrintHelpMessageIfHelpInvokedOnNonExistentComment() throws ClientException { // there is no such command as "cheese" - MainRunner runner = new MainRunner(null, 39); + MainRunner runner = new MainRunner(null, 45); runner.run("--help", "cheese"); } @@ -120,6 +123,14 @@ public void shouldPrintHelpForDelete() throws ClientException { assertThat(runner.stdout, containsString("Delete one or more assets from the repository, specified by id.")); } + @Test + public void shouldPrintHelpForFindAndDelete() throws ClientException { + MainRunner runner = new MainRunner(null, 30); + runner.run("--help", "findAndDelete"); + assertThat(runner.stdout, + containsString("Finds and deletes all the assets in the repository")); + } + @Test public void shouldPrintHelpForListAll() throws ClientException { MainRunner runner = new MainRunner(null, 27); diff --git a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/UploadTest.java b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/UploadTest.java index 60408a8..74ff18a 100644 --- a/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/UploadTest.java +++ b/cli-client/src/test/java/com/ibm/ws/lars/upload/cli/UploadTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Console; import java.io.File; @@ -41,8 +42,8 @@ import com.ibm.ws.lars.upload.cli.ClientException.HelpDisplay; import com.ibm.ws.massive.esa.MassiveEsa; -import com.ibm.ws.repository.common.enums.State; import com.ibm.ws.repository.common.enums.ResourceType; +import com.ibm.ws.repository.common.enums.State; import com.ibm.ws.repository.connections.RepositoryConnection; import com.ibm.ws.repository.connections.RestRepositoryConnection; import com.ibm.ws.repository.resources.EsaResource; @@ -223,7 +224,7 @@ public void testNoFiles() { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); try { main.run(new String[] { "--upload", "--url=http://example.org/" }); fail("ClientException not thrown"); @@ -241,7 +242,7 @@ public void testEmptyDirectoryShouldResultInNoFilesError() { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); try { main.run(new String[] { "--upload", "--url=http://example.org", "TestFile.esa" }); fail("ClientException not thrown"); @@ -258,7 +259,7 @@ public void testNoUrl() { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); try { main.run(new String[] { "--upload", "TestFile.esa" }); fail("ClientException not thrown"); @@ -276,7 +277,7 @@ public void testInvalidFile() { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); try { main.run(new String[] { "--upload", "--url=http://example.org", "TestFile.esa", "InvalidFile.esa" }); fail("ClientException not thrown"); @@ -294,7 +295,7 @@ public void testUpload() throws ClientException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); main.run(new String[] { "--upload", "--url=http://example.org", "TestFile.esa" }); assertEquals("Wrong files uploaded", Arrays.asList("TestFile.esa"), uploader.getFilesUploaded()); @@ -308,7 +309,7 @@ public void testMultipleUpload() throws ClientException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); main.run(new String[] { "--upload", "--url=http://example.org", "TestFile.esa", "TestFile2.esa", "TestFile3.esa" }); assertEquals("Wrong files uploaded", Arrays.asList("TestFile.esa", "TestFile2.esa", "TestFile3.esa"), uploader.getFilesUploaded()); @@ -324,7 +325,7 @@ public void testCredentials() throws ClientException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); main.run(new String[] { "--upload", "--url=http://example.org", "--username=jbloggs", "--password=foobar", "TestFile.esa" }); RestRepositoryConnection repoConnection = (RestRepositoryConnection) uploader.getLoginInfoEntry(); @@ -370,7 +371,7 @@ private Console getConsole() { ByteArrayOutputStream out = new ByteArrayOutputStream(); // test with a password prompt - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); main.run(new String[] { "--upload", "--url=http://example.org", "--username=jbloggs", "--password", "TestFile.esa" }); RestRepositoryConnection repoConnection = (RestRepositoryConnection) uploader.getLoginInfoEntry(); @@ -403,7 +404,7 @@ public void testShouldUploadContentsOfDirectory() throws Exception { new MockDirectoryWithFiles(); ByteArrayOutputStream out = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(out)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(out)); main.run(new String[] { "--upload", "--url=http://example.org", "superDirectory" }); @@ -418,7 +419,7 @@ public void testShouldGiveProgressIndication() throws Exception { new MockDirectoryWithFiles(); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - Main main = new Main(new PrintStream(outStream)); + Main main = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(outStream)); main.run(new String[] { "--upload", "--url=http://example.org", "superDirectory", "i-am-a-feature.esa" }); @@ -443,7 +444,7 @@ public void shouldGiveIndicationIfExistingResourceReplaced() throws Exception { // has been deleted when we upload our new resource. // We verify that we get a message telling us that the pre-existing file was deleted ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - Main main2 = new Main(new PrintStream(outStream)); + Main main2 = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(outStream)); main2.run(new String[] { "--upload", "--url=http://example.org", "superDirectory/cheese.esa" }); assertThat("Output incorrect", outStream.toString(), @@ -466,7 +467,7 @@ public void shouldGiveIndicationIfMultipleExistingResourceReplaced() throws Exce // have been deleted when we upload our new resource. // We verify that we get a message telling us that the pre-existing files were deleted ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - Main main2 = new Main(new PrintStream(outStream)); + Main main2 = new Main(new ByteArrayInputStream(new byte[0]), new PrintStream(outStream)); main2.run(new String[] { "--upload", "--url=http://example.org", "superDirectory/cheese.esa" }); assertEquals("Output incorrect", diff --git a/test-utils/src/main/java/com/ibm/ws/lars/testutils/TestProcess.java b/test-utils/src/main/java/com/ibm/ws/lars/testutils/TestProcess.java index df64f45..8abd9f1 100644 --- a/test-utils/src/main/java/com/ibm/ws/lars/testutils/TestProcess.java +++ b/test-utils/src/main/java/com/ibm/ws/lars/testutils/TestProcess.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.Reader; import java.util.List; @@ -36,6 +38,7 @@ public class TestProcess { private static final String NOT_YET_RUN = "Cannot check output before program has been run"; private final ProcessBuilder processBuilder; private Process process; + private String systemInput; private StringBuilder outputBuilder; private StringBuilder errorBuilder; private Integer returnCode; @@ -50,6 +53,17 @@ public TestProcess(List commandLine) { returnCode = null; } + /** + * Set up the TestProcess + * + * @param commandLine the command line (program followed by arguments) to execute + * @param systemInput the system input to be read during execution of the process + */ + public TestProcess(List commandLine, String systemInput) { + this(commandLine); + this.systemInput = systemInput; + } + /** * Run the program passed in the constructor and wait for it to finish * @@ -60,6 +74,12 @@ public void run() throws IOException { outputBuilder = new StringBuilder(); errorBuilder = new StringBuilder(); + if (systemInput != null) { + OutputStreamWriter osw = new OutputStreamWriter(process.getOutputStream()); + osw.write(systemInput); + osw.flush(); + } + ProcessStreamReader outReader = new ProcessStreamReader(process.getInputStream(), outputBuilder); new Thread(outReader).start();