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 = Boolean.getBoolean("module.tools.debug");
  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 
  60         // Create a temporary directory for JAM files and repositories.
  61         File tmp = new File(
  62             System.getProperty("test.scratch", "."), "JRepoTestDir").getCanonicalFile();
  63         JamUtils.recursiveDelete(tmp);
  64         tmp.mkdirs();
  65 
  66         // Create a directory for JAM files
  67         File jamDir = new File(tmp, "JRepoTestJamDir");
  68         JamUtils.recursiveDelete(jamDir);
  69         jamDir.mkdirs();
  70 
  71         /* Check install command */
  72 
  73         check(!jr.run(getArgs("install")) && usageOK(0));
  74         check(!jr.run(getArgs("install repo module")) && usageOK(0));
  75         check(!jr.run(getArgs("install -r repoDoesNotExist module")) && errorOK(1));
  76         check(!jr.run(getArgs("install -p -r repoDoesNotExist module")) && errorOK(9));
  77 
  78         // Create a directory for a local repository.
  79         File localRepoDir = new File(tmp, "JRepoTestLocalRepoDir");
  80         JamUtils.recursiveDelete(localRepoDir);
  81         localRepoDir.mkdirs();
  82         String repo = localRepoDir.getCanonicalPath();
  83 
  84         // Verify that you can't install a module which doesn't exist
  85         check(!jr.run(getArgs("install -r " + repo + " NoSuchModule")) && errorOK(1));
  86 
  87         // Each install must be of a different module
  88 
  89         // Verify silent output
  90         File jamFile = JamBuilder.createJam(
  91                 "jrepotest", "Example", "JRepoModuleA", "1.0", "platform", "arch", false, jamDir);
  92         jamFile.deleteOnExit();
  93         String jam = jamFile.getCanonicalPath();
  94         check(jr.run(getArgs("install -r " + repo + " " + jam)) && outputOK(0));
  95 
  96         // Verify verbose output
  97         jamFile = JamBuilder.createJam(
  98                 "jrepotest", "Example", "JRepoModuleB", "1.0", "platform", "arch", false, jamDir);
  99         jamFile.deleteOnExit();
 100         jam = jamFile.getCanonicalPath();
 101         check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
 102 
 103         // Verify multiple versions of same named module
 104         jamFile = JamBuilder.createJam(
 105                 "jrepotest", "Example", "JRepoModuleB", "2.0", "platform", "arch", false, jamDir);
 106         jamFile.deleteOnExit();
 107         jam = jamFile.getCanonicalPath();
 108         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 109         jamFile = JamBuilder.createJam(
 110                 "jrepotest", "Example", "JRepoModuleB", "2.5", "platform", "arch", false, jamDir);
 111         jamFile.deleteOnExit();
 112         jam = jamFile.getCanonicalPath();
 113         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 114 
 115         // Verify modules are installed
 116         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(6));
 117 
 118         // Verify -p is not applicable to install
 119         check(!jr.run(getArgs("install -p -r " + repo + " " + jam)) && usageOK(1));
 120 
 121         /* Check list command */
 122 
 123         check(!jr.run(getArgs("list")) && errorOK(0));
 124         check(jr.run(getArgs("list -p")) && outputOK(14));
 125         check(!jr.run(getArgs("list -v")) && errorOK(1));
 126         check(jr.run(getArgs("list -p -v")) && outputOK(14));
 127 
 128         // Common prefixes of "list"
 129         check(jr.run(getArgs("lis -r " + repo)) && outputOK(6));
 130         check(jr.run(getArgs("li -p -r " + repo)) && outputOK(20));
 131         check(jr.run(getArgs("l -v -r " + repo)) && outputOK(6));
 132         check(jr.run(getArgs("list -p -v -r " + repo)) && outputOK(20));
 133 
 134         // Nonexist things are not there
 135         check(!jr.run(getArgs("list ThisWillNotBeFound")) && outputOK(0));
 136         check(!jr.run(getArgs("list -v ThisWillNotBeFound")) && errorOK(1));
 137 
 138         // Bootstrap repository contents are there
 139         check(!jr.run(getArgs("list java.se.core")) && errorOK(0));
 140         check(jr.run(getArgs("list -p java.se.core")) && outputOK(3));
 141         check(!jr.run(getArgs("list -v java.se.core")) && errorOK(1));
 142         check(jr.run(getArgs("list -p -v java.se.core")) && outputOK(3));
 143 
 144         // Various options work
 145         check(jr.run(getArgs("list -r " + repo + " JRepoModuleA")) && outputOK(3));
 146         check(jr.run(getArgs("list -p -r " + repo + " JRepoModuleA")) && outputOK(3));
 147         check(jr.run(getArgs("list -v -r " + repo + " JRepoModuleA")) && outputOK(3));
 148         check(jr.run(getArgs("list -p -v -r " + repo + " JRepoModuleA")) && outputOK(3));
 149 
 150         // Given module name is treated as substring of full module names
 151         check(jr.run(getArgs("list -r " + repo + " JRepoModule")) && outputOK(6));
 152         check(jr.run(getArgs("list -p -r " + repo + " JRepoModu")) && outputOK(6));
 153         check(jr.run(getArgs("list -v -r " + repo + " JRepo")) && outputOK(6));
 154         check(jr.run(getArgs("list -p -v -r " + repo + " JR")) && outputOK(6));
 155 
 156         /* Check uninstall command */
 157 
 158         check(!jr.run(getArgs("uninstall")) && usageOK(0));
 159         check(!jr.run(getArgs("uninstall repo MODULE")) && usageOK(0));
 160         check(!jr.run(getArgs("uninstall -r repoDoesNotExist module")) && errorOK(1));
 161         check(!jr.run(getArgs("uninstall -p -r repoDoesNotExist module")) && errorOK(9));
 162 
 163         check(!jr.run(getArgs("uninstall -r " + repo + " Fred")) && errorOK(0));
 164         check(!jr.run(getArgs("uninstall -v -r " + repo + " Fred")) && errorOK(1));
 165 
 166         // Install one more module for tests below
 167         jamFile = JamBuilder.createJam(
 168                 "jrepotest", "Example", "JRepoModuleC", "1.0", "platform", "arch", false, jamDir);
 169         jamFile.deleteOnExit();
 170         jam = jamFile.getCanonicalPath();
 171         check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
 172 
 173         // Verify a straightforward uninstall.
 174         check(jr.run(getArgs("unin -v -r " + repo + " JRepoModuleA")) && outputOK(1));
 175 
 176         // Verify we can't uninstall from module name alone when there is more
 177         // than one version with that name...
 178         check(!jr.run(getArgs("un -r " + repo + " JRepoModuleB")) && outputOK(0));
 179 
 180         // ... and that with -v the JRepo says what ones there are...
 181         check(!jr.run(getArgs("un -v -r " + repo + " JRepoModuleB")) && errorOK(4));
 182 
 183         // ... but that by appending the version, uninstall succeeds.
 184         check(jr.run(getArgs("un -v -r " + repo + " JRepoModuleB 2.0")) && outputOK(1));
 185         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(5));
 186 
 187         // Verify that the -f flag causes the remaining JRepoModuleB versions
 188         // to be uninstalled
 189         check(jr.run(getArgs("un -v -f -r " + repo + " JRepoModuleB")) && outputOK(2));
 190         check(jr.run(getArgs("list -v -r " + repo)) && outputOK(3));
 191 
 192         // Install more modules to verify -i works
 193         jamFile = JamBuilder.createJam(
 194                 "jrepotest", "Interact", "JRepoModuleD", "2.7", "platform", "arch", false, jamDir);
 195         jamFile.deleteOnExit();
 196         jam = jamFile.getCanonicalPath();
 197         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 198         jamFile = JamBuilder.createJam(
 199                 "jrepotest", "Interact", "JRepoModuleD", "3.1", "platform", "arch", false, jamDir);
 200         jamFile.deleteOnExit();
 201         jam = jamFile.getCanonicalPath();
 202         check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
 203 
 204         // This reader will let us delete the module JRepoModuleD version 3.1.
 205         class MockReader extends BufferedReader {
 206             MockReader() {
 207                 super(new StringReader("1\n"));
 208             }
 209         }
 210         JRepo jr2 = new JRepo(
 211             new PrintStream(bout), new PrintStream(berr), new MockReader());
 212         check(jr2.run(getArgs("un -v -i -r " + repo + " JRepoModuleD")) && outputOK(5));
 213         check(jr2.run(getArgs("list -v -r " + repo)) && outputOK(4));
 214 
 215         /*
 216          * End of checks on LocalRepository, now try a few on URLRepository.
 217          */
 218 
 219         // Create a directory for a url repository.
 220         File urlRepoDir = new File(tmp, "JRepoTestURLRepoDir");
 221         JamUtils.recursiveDelete(urlRepoDir);
 222         urlRepoDir.mkdirs();
 223 
 224         File repoDownloadDir = new File(urlRepoDir, "download");
 225         Map<String, String> config = new HashMap<String, String>();
 226         config.put(
 227             "sun.module.repository.URLRepository.cacheDirectory",
 228             repoDownloadDir.getAbsolutePath());
 229 
 230         String urlRepoPath = urlRepoDir.getCanonicalPath();
 231         if (!urlRepoPath.startsWith("/")) {
 232             urlRepoPath = "/" + urlRepoPath;
 233         }
 234         urlRepoPath = "file://" + urlRepoPath;
 235         Repository urlrepo = Modules.newURLRepository("JRepoTestURLRepository",
 236                                                       new URL(urlRepoPath), config);
 237 
 238         // Verify multiple versions of same named module
 239         jamFile = JamBuilder.createJam(
 240                 "jrepotest", "Example", "URLModuleX", "7.0", "platform", "arch", false, jamDir);
 241         jamFile.deleteOnExit();
 242         jam = jamFile.getCanonicalPath();
 243         check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
 244 
 245         jamFile = JamBuilder.createJam(
 246                 "jrepotest", "Example", "URLModuleX", "13.0", "platform", "arch", false, jamDir);
 247         jamFile.deleteOnExit();
 248         jam = jamFile.getCanonicalPath();
 249         check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
 250 
 251         // Verify list
 252         check(jr.run(getArgs("list -v -r " + urlRepoPath)) && outputOK(4));
 253 
 254         // Verify uninstall
 255         check(jr.run(getArgs("un -v -f -r " + urlRepoPath + " URLModuleX 13")) && outputOK(1));
 256 
 257         // Verify uninstall worked
 258         check(jr.run(getArgs("list -v -r " + urlRepoPath)) && outputOK(3));
 259 
 260         JRepo jr3 = new JRepo(System.out, System.err, null);
 261         jr3.run(getArgs("list -v -r " + urlRepoPath));
 262 
 263         // Cleanup test directories
 264         if (failed == 0) {
 265             JamUtils.recursiveDelete(jamDir);
 266             JamUtils.recursiveDelete(localRepoDir);
 267             JamUtils.recursiveDelete(urlRepoDir);
 268         }
 269     }
 270 
 271     /** Return an array of Strings from the given String. */
 272     static String[] getArgs(String s) {
 273         List<String> args = new ArrayList<String>();
 274         StringTokenizer st = new StringTokenizer(s);
 275         while (st.hasMoreTokens()) {
 276             String token = st.nextToken();
 277             if (debug) System.err.println("adding arg " + token);
 278             args.add(token);
 279         }
 280         if (debug) System.err.println("args length is " + args.size());
 281         return args.toArray(new String[0]);
 282     }
 283 
 284     /**
 285      * If the output is OK, returns true.  For now, being OK means only
 286      * having {code len} lines.
 287      */
 288     static boolean checkOutput(int len, ByteArrayOutputStream baos) throws Throwable {
 289         String s = baos.toString("ASCII");
 290         BufferedReader r = new BufferedReader(new StringReader(s));
 291         int count = 0;
 292         while (r.readLine() != null) {
 293             count++;
 294         }
 295         if (debug) System.err.println(
 296             "Checking expected length " + len
 297             + " = given length " + count
 298             + " on '" + s + "'");
 299         bout.reset();
 300         berr.reset();
 301         return len == count;
 302     }
 303 
 304     /** Check stdout. */
 305     static boolean outputOK(int len) throws Throwable {
 306         return checkOutput(len, bout);
 307     }
 308 
 309     /** Check stderr. */
 310     static boolean errorOK(int len) throws Throwable {
 311         return checkOutput(len, berr);
 312     }
 313 
 314     /** Check that usage is provided as expected. */
 315     static boolean usageOK(int len) throws Throwable {
 316         // Add number of default lines of usage output to given value.
 317         return checkOutput(8 + len, berr);
 318     }
 319 
 320     //--------------------- Infrastructure ---------------------------
 321     static volatile int passed = 0, failed = 0;
 322     static boolean pass() {passed++; return true;}
 323     static boolean fail() {failed++; Thread.dumpStack(); return false;}
 324     static boolean fail(String msg) {System.err.println(msg); return fail();}
 325     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
 326     static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
 327     static boolean equal(Object x, Object y) {
 328         if (x == null ? y == null : x.equals(y)) return pass();
 329         else return fail(x + " not equal to " + y);}
 330     public static void main(String[] args) throws Throwable {
 331         try {realMain(args);} catch (Throwable t) {unexpected(t);}
 332         System.out.println("\nPassed = " + passed + " failed = " + failed);
 333         if (failed > 0) throw new AssertionError("Some tests failed");}
 334 }