1 /*
   2  * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  */
  23 
  24 import java.io.*;
  25 import java.module.*;
  26 import java.net.*;
  27 import java.util.*;
  28 import sun.module.JamUtils;
  29 import sun.module.tools.JRepo;
  30 
  31 /**
  32  * @test
  33  * @summary Test execution of JRepo
  34  * @library ..
  35  * @compile -XDignore.symbol.file JRepoTest.java ../JamBuilder.java
  36  * @run main JRepoTest
  37  */
  38 public class JRepoTest {
  39     private static final boolean debug = true;/*Boolean.getBoolean("module.tools.debug"); ZZZ */
  40 
  41     static final ByteArrayOutputStream bout = new ByteArrayOutputStream();
  42     static final ByteArrayOutputStream berr = new ByteArrayOutputStream();
  43 
  44     public static void realMain(String args[]) throws Throwable {
  45         JRepo jr = new JRepo(new PrintStream(bout), new PrintStream(berr), null);
  46 
  47         /*
  48          * Check common error reporting.
  49          */
  50         check(!jr.run(new String[] {" "}) && usageOK(0));
  51         check(!jr.run(getArgs("notASubCcommand")) && usageOK(0));
  52         check(!jr.run(getArgs("list -+")) && usageOK(1));
  53 
  54         /*
  55          * Do many tests on a LocalRepository, then a few on a URLRepository
  56          * as a sanity check.
  57          */
  58 
  59         // Create a temporary directory for JAM files and repositories.
  60         File tmp = new File(
  61             System.getProperty("test.scratch", "."), "JRepoTestDir").getCanonicalFile();
  62         JamUtils.recursiveDelete(tmp);
  63         tmp.mkdirs();
  64 
  65         // Create a directory for JAM files
  66         File jamDir = new File(tmp, "JRepoTestJamDir");
  67         JamUtils.recursiveDelete(jamDir);
  68         jamDir.mkdirs();
  69 
  70         /* Check install command */
  71 
  72         check(!jr.run(getArgs("install")) && usageOK(0));
  73         check(!jr.run(getArgs("install repo module")) && usageOK(0));
  74         check(!jr.run(getArgs("install -r repoDoesNotExist module")) && errorOK(1));
  75         check(!jr.run(getArgs("install -p -r repoDoesNotExist module")) && errorOK(13));
  76 
  77         // Create a directory for a local repository.
  78         File localRepoDir = new File(tmp, "JRepoTestLocalRepoDir");
  79         JamUtils.recursiveDelete(localRepoDir);
  80         localRepoDir.mkdirs();
  81         String repo = localRepoDir.getCanonicalPath();
  82 
  83         // Verify that you can't install a module which doesn't exist
  84         check(!jr.run(getArgs("install -r " + repo + " NoSuchModule")) && errorOK(1));
  85 
  86         // Each install must be of a different module
  87 
  88         // Verify silent output
  89         File jamFile = JamBuilder.createJam(
  90                 "jrepotest", "Example", "JRepoModuleA", "1.0", "platform", "arch", false, jamDir);
  91         jamFile.deleteOnExit();
  92         String jam = jamFile.getCanonicalPath();
  93         check(jr.run(getArgs("install -r " + repo + " " + jam)) && outputOK(0));
  94 
  95         // Verify verbose output
  96         jamFile = JamBuilder.createJam(
  97                 "jrepotest", "Example", "JRepoModuleB", "1.0", "platform", "arch", false, jamDir);
  98         jamFile.deleteOnExit();
  99         jam = jamFile.getCanonicalPath();
 100         check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
 101 
 102         // Verify multiple versions of same named module
 103         jamFile = JamBuilder.createJam(
 104                 "jrepotest", "Example", "JRepoModuleB", "2.0", "platform", "arch", false, jamDir);
 105         jamFile.deleteOnExit();
 106         jam = jamFile.getCanonicalPath();
 107         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 108         jamFile = JamBuilder.createJam(
 109                 "jrepotest", "Example", "JRepoModuleB", "2.5", "platform", "arch", false, jamDir);
 110         jamFile.deleteOnExit();
 111         jam = jamFile.getCanonicalPath();
 112         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 113 
 114         // Verify modules are installed
 115         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(6));
 116 
 117         // Verify -p is not applicable to install
 118         check(!jr.run(getArgs("install -p -r " + repo + " " + jam)) && usageOK(1));
 119 
 120         /* Check list command */
 121 
 122         check(!jr.run(getArgs("list")) && errorOK(0));
 123         check(jr.run(getArgs("list -p")) && outputOK(14));
 124         check(!jr.run(getArgs("list -v")) && errorOK(1));
 125         check(jr.run(getArgs("list -p -v")) && outputOK(22));
 126 
 127         // Common prefixes of "list"
 128         check(jr.run(getArgs("lis -r " + repo)) && outputOK(6));
 129         check(jr.run(getArgs("li -p -r " + repo)) && outputOK(20));
 130         check(jr.run(getArgs("l -v -r " + repo)) && outputOK(6));
 131         check(jr.run(getArgs("list -p -v -r " + repo)) && outputOK(28));
 132 
 133         // Nonexist things are not there
 134         check(!jr.run(getArgs("list ThisWillNotBeFound")) && outputOK(0));
 135         check(!jr.run(getArgs("list -v ThisWillNotBeFound")) && errorOK(1));
 136 
 137         // Bootstrap repository contents are there
 138         check(!jr.run(getArgs("list java.se.core")) && errorOK(0));
 139         check(jr.run(getArgs("list -p java.se.core")) && outputOK(3));
 140         check(!jr.run(getArgs("list -v java.se.core")) && errorOK(1));
 141         check(jr.run(getArgs("list -p -v java.se.core")) && outputOK(11));
 142 
 143         // Various options work
 144         check(jr.run(getArgs("list -r " + repo + " JRepoModuleA")) && outputOK(3));
 145         check(jr.run(getArgs("list -p -r " + repo + " JRepoModuleA")) && outputOK(3));
 146         check(jr.run(getArgs("list -v -r " + repo + " JRepoModuleA")) && outputOK(3));
 147         check(jr.run(getArgs("list -p -v -r " + repo + " JRepoModuleA")) && outputOK(11));
 148 
 149         // Given module name is treated as substring of full module names
 150         check(jr.run(getArgs("list -r " + repo + " JRepoModule")) && outputOK(6));
 151         check(jr.run(getArgs("list -p -r " + repo + " JRepoModu")) && outputOK(6));
 152         check(jr.run(getArgs("list -v -r " + repo + " JRepo")) && outputOK(6));
 153         check(jr.run(getArgs("list -p -v -r " + repo + " JR")) && outputOK(14));
 154 
 155         /* Check uninstall command */
 156 
 157         check(!jr.run(getArgs("uninstall")) && usageOK(0));
 158         check(!jr.run(getArgs("uninstall repo MODULE")) && usageOK(0));
 159         check(!jr.run(getArgs("uninstall -r repoDoesNotExist module")) && errorOK(1));
 160         check(!jr.run(getArgs("uninstall -p -r repoDoesNotExist module")) && errorOK(13));
 161 
 162         check(!jr.run(getArgs("uninstall -r " + repo + " Fred")) && errorOK(0));
 163         check(!jr.run(getArgs("uninstall -v -r " + repo + " Fred")) && errorOK(1));
 164 
 165         // Install one more module for tests below
 166         jamFile = JamBuilder.createJam(
 167                 "jrepotest", "Example", "JRepoModuleC", "1.0", "platform", "arch", false, jamDir);
 168         jamFile.deleteOnExit();
 169         jam = jamFile.getCanonicalPath();
 170         check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
 171 
 172         // Verify a straightforward uninstall.
 173         check(jr.run(getArgs("unin -v -r " + repo + " JRepoModuleA")) && outputOK(1));
 174 
 175         // Verify we can't uninstall from module name alone when there is more
 176         // than one version with that name...
 177         check(!jr.run(getArgs("un -r " + repo + " JRepoModuleB")) && outputOK(0));
 178 
 179         // ... and that with -v the JRepo says what ones there are...
 180         check(!jr.run(getArgs("un -v -r " + repo + " JRepoModuleB")) && errorOK(4));
 181 
 182         // ... but that by appending the version, uninstall succeeds.
 183         check(jr.run(getArgs("un -v -r " + repo + " JRepoModuleB 2.0")) && outputOK(1));
 184         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(5));
 185 
 186         // Verify that the -f flag causes the remaining JRepoModuleB versions
 187         // to be uninstalled
 188         check(jr.run(getArgs("un -v -f -r " + repo + " JRepoModuleB")) && outputOK(2));
 189         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(3));
 190 
 191         // Install more modules to verify -i works
 192         jamFile = JamBuilder.createJam(
 193                 "jrepotest", "Interact", "JRepoModuleD", "2.7", "platform", "arch", false, jamDir);
 194         jamFile.deleteOnExit();
 195         jam = jamFile.getCanonicalPath();
 196         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 197         jamFile = JamBuilder.createJam(
 198                 "jrepotest", "Interact", "JRepoModuleD", "3.1", "platform", "arch", false, jamDir);
 199         jamFile.deleteOnExit();
 200         jam = jamFile.getCanonicalPath();
 201         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 202 
 203         // This reader will let us delete the module JRepoModuleD version 3.1.
 204         class MockReader extends BufferedReader {
 205             MockReader() {
 206                 super(new StringReader("1\n"));
 207             }
 208         }
 209         JRepo jr2 = new JRepo(
 210             new PrintStream(bout), new PrintStream(berr), new MockReader());
 211         check(jr2.run(getArgs("un -v -i -r " + repo + " JRepoModuleD")) && outputOK(5));
 212         check(jr2.run(getArgs("list -v -r " + repo)) && outputOK(4));
 213 
 214         /*
 215          * End of checks on LocalRepository, now try a few on URLRepository.
 216          */
 217 
 218         // Create a directory for a url repository.
 219         File urlRepoDir = new File(tmp, "JRepoTestURLRepoDir");
 220         JamUtils.recursiveDelete(urlRepoDir);
 221         urlRepoDir.mkdirs();
 222 
 223         File repoDownloadDir = new File(urlRepoDir, "download");
 224         Map<String, String> config = new HashMap<String, String>();
 225         config.put(
 226             "sun.module.repository.URLRepository.cacheDirectory",
 227             repoDownloadDir.getAbsolutePath());
 228 
 229         String urlRepoPath = urlRepoDir.getCanonicalPath();
 230         if (!urlRepoPath.startsWith("/")) {
 231             urlRepoPath = "/" + urlRepoPath;
 232         }
 233         urlRepoPath = "file://" + urlRepoPath;
 234         Repository urlrepo = Modules.newURLRepository("JRepoTestURLRepository",
 235                                                       new URL(urlRepoPath), config);
 236 
 237         // Verify multiple versions of same named module
 238         jamFile = JamBuilder.createJam(
 239                 "jrepotest", "Example", "URLModuleX", "7.0", "platform", "arch", false, jamDir);
 240         jamFile.deleteOnExit();
 241         jam = jamFile.getCanonicalPath();
 242         check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
 243 
 244         jamFile = JamBuilder.createJam(
 245                 "jrepotest", "Example", "URLModuleX", "13.0", "platform", "arch", false, jamDir);
 246         jamFile.deleteOnExit();
 247         jam = jamFile.getCanonicalPath();
 248         check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
 249 
 250         // Verify list
 251         check(jr.run(getArgs("list -v -r " + urlRepoPath)) && outputOK(4));
 252 
 253         // Verify uninstall
 254         check(jr.run(getArgs("un -v -f -r " + urlRepoPath + " URLModuleX 13")) && outputOK(1));
 255 
 256         // Verify uninstall worked
 257         check(jr.run(getArgs("list -v -r " + urlRepoPath)) && outputOK(3));
 258 
 259         JRepo jr3 = new JRepo(System.out, System.err, null);
 260         jr3.run(getArgs("list -v -r " + urlRepoPath));
 261 
 262         // Cleanup test directories
 263         if (failed == 0) {
 264             JamUtils.recursiveDelete(jamDir);
 265             JamUtils.recursiveDelete(localRepoDir);
 266             JamUtils.recursiveDelete(urlRepoDir);
 267         }
 268     }
 269 
 270     /** Return an array of Strings from the given String. */
 271     static String[] getArgs(String s) {
 272         List<String> args = new ArrayList<String>();
 273         StringTokenizer st = new StringTokenizer(s);
 274         while (st.hasMoreTokens()) {
 275             String token = st.nextToken();
 276             if (debug) System.err.println("adding arg " + token);
 277             args.add(token);
 278         }
 279         if (debug) System.err.println("args length is " + args.size());
 280         return args.toArray(new String[0]);
 281     }
 282 
 283     /**
 284      * If the output is OK, returns true.  For now, being OK means only
 285      * having {code len} lines.
 286      */
 287     static boolean checkOutput(int len, ByteArrayOutputStream baos) throws Throwable {
 288         String s = baos.toString("ASCII");
 289         BufferedReader r = new BufferedReader(new StringReader(s));
 290         int count = 0;
 291         while (r.readLine() != null) {
 292             count++;
 293         }
 294         if (debug) System.err.println(
 295             "Checking expected length " + len
 296             + " = given length " + count
 297             + " on '" + s + "'");
 298         bout.reset();
 299         berr.reset();
 300         return len == count;
 301     }
 302 
 303     /** Check stdout. */
 304     static boolean outputOK(int len) throws Throwable {
 305         return checkOutput(len, bout);
 306     }
 307 
 308     /** Check stderr. */
 309     static boolean errorOK(int len) throws Throwable {
 310         return checkOutput(len, berr);
 311     }
 312 
 313     /** Check that usage is provided as expected. */
 314     static boolean usageOK(int len) throws Throwable {
 315         // Add number of default lines of usage output to given value.
 316         return checkOutput(12 + len, berr);
 317     }
 318 
 319     //--------------------- Infrastructure ---------------------------
 320     static volatile int passed = 0, failed = 0;
 321     static boolean pass() {passed++; return true;}
 322     static boolean fail() {failed++; Thread.dumpStack(); return false;}
 323     static boolean fail(String msg) {System.err.println(msg); return fail();}
 324     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 325     static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
 326     static boolean equal(Object x, Object y) {
 327         if (x == null ? y == null : x.equals(y)) return pass();
 328         else return fail(x + " not equal to " + y);}
 329     public static void main(String[] args) throws Throwable {
 330         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 331         System.out.println("\nPassed = " + passed + " failed = " + failed);
 332         if (failed > 0) throw new AssertionError("Some tests failed");}
 333 }