001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.tests.derbynet.DerbyNetAutoStart
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.functionTests.tests.derbynet;
023:
024: import org.apache.derby.iapi.reference.Property;
025: import org.apache.derby.drda.NetworkServerControl;
026:
027: import org.apache.derbyTesting.functionTests.harness.jvm;
028: import org.apache.derby.tools.ij;
029: import org.apache.derbyTesting.functionTests.util.TestUtil;
030:
031: import java.io.File;
032: import java.io.IOException;
033: import java.io.FileOutputStream;
034: import java.io.ByteArrayOutputStream;
035: import java.io.BufferedReader;
036: import java.io.InputStreamReader;
037: import java.io.OutputStream;
038: import java.io.PrintStream;
039: import java.io.RandomAccessFile;
040: import java.io.FileReader;
041: import java.io.FileInputStream;
042:
043: import java.net.InetAddress;
044:
045: import java.sql.DriverManager;
046: import java.sql.Connection;
047: import java.sql.DatabaseMetaData;
048: import java.sql.ResultSet;
049: import java.sql.SQLException;
050: import java.sql.Statement;
051:
052: import java.util.Enumeration;
053: import java.util.Properties;
054: import java.util.Vector;
055:
056: /**
057: * Test the network server derby.drda.startNetworkServer property.
058: *
059: * Test that:
060: *<ul>
061: *<li>The network server is started when the property value is true.
062: *<li>The network server is not started when the property value is false.
063: *<li>The default port number is used when the port property is not specified.
064: *<li>The server uses a non-default port when a port property is set.
065: *<li>A message is printed to derby.log when the server is already started.
066: *</ul>
067: */
068: public class DerbyNetAutoStart {
069:
070: protected static boolean passed = true;
071:
072: private static final String JUST_START_SERVER_ARG = "justStartServer=";
073: private static Connection drdaConn;
074: private static Connection embeddedConn;
075: private static int testNumber = 0;
076: private static int portNumber;
077: private static String hostName;
078: private static String homeDir;
079: private static String databaseName;
080: private static Properties baseProperties = new Properties();
081: private static StringBuffer basePropertiesSB = new StringBuffer();
082: private static File derbyPropertiesFile;
083: private static final Properties authenticationProperties;
084: static {
085: authenticationProperties = new Properties();
086: authenticationProperties.put("user", "admin");
087: authenticationProperties.put("password", "admin");
088: }
089: private static PrintStream realSystemOut;
090: private static ByteArrayOutputStream serverOutputBOS = new ByteArrayOutputStream();
091: private static PrintStream serverOutputOut = new PrintStream(
092: serverOutputBOS);
093:
094: public static void main(String[] args) {
095: setup(args);
096: runAllTests();
097: if (passed) {
098: System.out.println("PASSED.");
099: System.exit(0);
100: } else {
101: System.out.println("FAILED.");
102: System.exit(1);
103: }
104: } // end of main
105:
106: protected static void setup(String[] args) {
107: realSystemOut = System.out;
108: try {
109: TestUtil.loadDriver();
110:
111: ij.getPropertyArg(args);
112: homeDir = System.getProperty("derby.system.home", ".");
113: hostName = TestUtil.getHostName();
114:
115: for (int i = 0; i < args.length; i++) {
116: if (args[i].startsWith(JUST_START_SERVER_ARG)) {
117: PrintStream out = getPrintStream(homeDir
118: + File.separatorChar + "serverOutput.txt");
119: System.setOut(out);
120: System.setErr(out);
121:
122: Class.forName(
123: "org.apache.derby.jdbc.EmbeddedDriver")
124: .newInstance();
125: try {
126: portNumber = Integer.parseInt(args[i]
127: .substring(JUST_START_SERVER_ARG
128: .length()));
129: } catch (Exception e) {
130: portNumber = -1; // use the default
131: }
132: if (portNumber <= 0)
133: portNumber = NetworkServerControl.DEFAULT_PORTNUMBER;
134:
135: NetworkServerControl server = new NetworkServerControl(
136: InetAddress.getByName(hostName), portNumber);
137: server.start(null);
138: // Wait for server to come up
139: for (int j = 0; j < 60; j++) {
140: Thread.sleep(1000);
141: if (isServerStarted(server))
142: break;
143: }
144: // Block so other process can get connections
145: while (isServerStarted(server))
146: Thread.sleep(500);
147: System.exit(0);
148: }
149: }
150:
151: derbyPropertiesFile = new File(homeDir + File.separatorChar
152: + "derby.properties");
153:
154: try {
155: FileReader propertiesReader = new FileReader(
156: derbyPropertiesFile);
157: for (int c; (c = propertiesReader.read()) != -1;)
158: basePropertiesSB.append((char) c);
159: baseProperties.load(new FileInputStream(
160: derbyPropertiesFile));
161: } catch (IOException ioe) {
162: }
163: } catch (Exception e) {
164: System.out.println(e.getClass().getName() + " thrown: "
165: + e.getMessage());
166: e.printStackTrace();
167: passed = false;
168: }
169: if (!passed)
170: System.exit(1);
171: } // end of setup
172:
173: protected static void runAllTests() {
174: testNumber = 0;
175: try {
176: portNumber = NetworkServerControl.DEFAULT_PORTNUMBER;
177: if (startTest(new String[] { Property.START_DRDA, "true" })) {
178: endTest(true);
179: }
180:
181: portNumber = 31415;
182: if (startTest(new String[] { Property.START_DRDA, "true",
183: Property.DRDA_PROP_PORTNUMBER,
184: String.valueOf(portNumber) })) {
185: endTest(true);
186: }
187:
188: portNumber = -1;
189: if (startTest(new String[] { Property.START_DRDA, "false" })) {
190: deleteDir(homeDir + File.separatorChar + databaseName);
191:
192: try {
193: drdaConn = DriverManager.getConnection(TestUtil
194: .getJdbcUrlPrefix()
195: + databaseName, authenticationProperties);
196: passed = false;
197: System.out
198: .println(" The network server was started though "
199: + Property.START_DRDA + "=false.");
200: } catch (SQLException sqle) {
201: }
202: endTest(false);
203: }
204:
205: if (startTest(new String[] {})) {
206: try {
207: drdaConn = DriverManager.getConnection(TestUtil
208: .getJdbcUrlPrefix()
209: + "database" + testNumber,
210: authenticationProperties);
211: passed = false;
212: System.out
213: .println(" The network server was started though "
214: + Property.START_DRDA
215: + " was not set.");
216: } catch (SQLException sqle) {
217: }
218: endTest(false);
219: }
220: // Start the network server in a different JVM and check that autostart handles it.
221: testExtantNetServer();
222: } catch (Exception e) {
223: System.out.println(e.getClass().getName() + " thrown: "
224: + e.getMessage());
225: e.printStackTrace();
226: passed = false;
227: }
228: }
229:
230: private static PrintStream getPrintStream(String fileName) {
231: try {
232: return new PrintStream(new FileOutputStream(fileName));
233: } catch (Exception e) {
234: System.out.println("Could not create " + fileName);
235: System.out.println(e.getMessage());
236: System.exit(1);
237: return null;
238: }
239: } // end of getPrintStream
240:
241: private static final String logFileProperty = "derby.stream.error.file";
242:
243: private static void testExtantNetServer() throws Exception
244: {
245: RandomAccessFile logFile;
246: String portStr;
247: String logFileName = homeDir + File.separator + "derby.log";
248:
249: announceTest();
250:
251: long startLogFileLength = getLogFileLength( logFileName);
252: String logAppendProp = System.getProperty( Property.LOG_FILE_APPEND);
253: if( logAppendProp == null)
254: logAppendProp = baseProperties.getProperty( Property.LOG_FILE_APPEND);
255: boolean appendingToLog = ( logAppendProp != null && (new Boolean( logAppendProp).booleanValue()));
256:
257: if( ! writeDerbyProperties( new String[]{}))
258: return;
259:
260: // Start the network server in another process
261: jvm jvm = null;
262: try
263: {
264: jvm = jvm.getCurrentJvm();
265: }
266: catch( Exception e)
267: {
268:
269: passed = false;
270: System.out.println( " Could not get the current JVM:");
271: System.out.println( " " + e.getMessage());
272: return;
273: }
274: portNumber = -1;
275: Vector vCmd = jvm.getCommandLine();
276: Properties systemProperties = System.getProperties();
277: String cmd[] = new String[ vCmd.size() + systemProperties.size() + 3];
278: int i;
279: for( i = 0; i < vCmd.size(); i++)
280: cmd[i] = (String) vCmd.elementAt(i);
281: for( Enumeration enum = systemProperties.keys(); enum.hasMoreElements();)
282: {
283: String propName = (String) enum.nextElement();
284: if( ! propName.equals( logFileProperty))
285: cmd[i++] = "-D" + propName + "=" + (String) systemProperties.get( propName);
286: }
287: cmd[i++] = "-D" + logFileProperty + "=derbynet.log";
288: cmd[i++] = "org.apache.derbyTesting.functionTests.tests.derbynet.DerbyNetAutoStart";
289: if( portNumber > 0)
290: {
291: portStr = String.valueOf( portNumber);
292: cmd[i++] = JUST_START_SERVER_ARG + ((portNumber > 0) ? String.valueOf( portNumber) : "");
293: portStr = ":" + portStr;
294: }
295: else
296: {
297: portStr = "1527";
298: cmd[i++] = JUST_START_SERVER_ARG;
299: }
300: /*
301: System.out.println("Cmd:");
302: for (int c = 0; c < cmd.length;c++)
303: System.out.print(cmd[c] + " ");
304: System.out.println("");
305: */
306:
307: Process serverProcess = Runtime.getRuntime().exec( cmd);
308: // Wait for to start
309: String dbUrl = TestUtil.getJdbcUrlPrefix(hostName,
310: Integer.parseInt(portStr)) +
311: "database1";
312: Connection drdaConn = null;
313: for( int ntries = 1; ; ntries++)
314: {
315: try
316: {
317: Thread.sleep(500);
318: }
319: catch( InterruptedException ie){};
320:
321: try
322: {
323: drdaConn = DriverManager.getConnection( dbUrl, authenticationProperties);
324: break;
325: }
326: catch( SQLException sqle)
327: {
328: if( ntries > 20)
329: {
330: System.out.println( "Server start failed: " +
331: sqle.getMessage());
332: sqle.printStackTrace();
333: passed = false;
334: return;
335: }
336: }
337:
338: }
339:
340:
341: try
342: {
343: String[] properties;
344: if( portNumber <= 0)
345: properties = new String[] {Property.START_DRDA, "true"};
346: else
347: properties = new String[] {Property.START_DRDA, "true",
348: Property.DRDA_PROP_PORTNUMBER,
349: String.valueOf( portNumber)};
350: portNumber = -1;
351: if( runTest( properties))
352: {
353: checkConn( drdaConn, "network");
354: checkConn( embeddedConn, "embedded");
355: drdaConn.close();
356:
357: endTest( false);
358:
359: // There should be a warning in the derby.log file.
360: try
361: {
362: // The network server is started in a different thread, so give it a little time
363: // to write the message
364: Thread.sleep(1000);
365: logFile = new RandomAccessFile( logFileName, "r");
366: if( appendingToLog)
367: logFile.seek( startLogFileLength);
368: }
369: catch( Exception e)
370: {
371: System.out.println( "Cannot open derby.log: " + e.getMessage());
372: passed = false;
373: drdaConn.close();
374: stopServer( serverProcess);
375: return;
376: }
377: if( !checkLog( logFileName, new String[] {"An exception was thrown during network server startup"}))
378: {
379: // Was the network server started? Print out the names of the threads
380: System.out.println( "Active threads:");
381: ThreadGroup tg = Thread.currentThread().getThreadGroup();
382: while( tg.getParent() != null)
383: tg = tg.getParent();
384: Thread[] activeThreads = new Thread[ 16*Thread.activeCount()];
385: int threadCount = tg.enumerate( activeThreads, true);
386: for( int idx = 0; idx < threadCount; idx++)
387: System.out.println( " " + activeThreads[idx].getName());
388: // Is the server process still running?
389: try
390: {
391: int ev = serverProcess.exitValue();
392: System.out.println( "The separate server process exited prematurely with code " + ev);
393: }
394: catch( IllegalThreadStateException itse)
395: {
396: System.out.println( "The server process seems to be running.");
397: }
398: }
399: }
400: }
401: catch( Exception e)
402: {
403: e.printStackTrace();
404: passed = false;
405: }
406: stopServer( serverProcess);
407: } // end of testExtantNetServer
408:
409: private static long getLogFileLength(String logFileName) {
410: try {
411: RandomAccessFile logFile = new RandomAccessFile(
412: logFileName, "r");
413: long length = logFile.length();
414: logFile.close();
415: return length;
416: } catch (Exception e) {
417: return 0;
418: }
419: }
420:
421: private static void checkConn(Connection conn, String label) {
422: try {
423: DatabaseMetaData dbmd = conn.getMetaData();
424: ResultSet rs = dbmd.getSchemas();
425: while (rs.next())
426: ;
427: rs.close();
428: } catch (SQLException sqle) {
429: passed = false;
430: System.out.println("Could not use the " + label
431: + " connection:");
432: System.out.println(" " + sqle.getMessage());
433: }
434: } // end of checkConn
435:
436: private static void stopServer(Process serverProcess) {
437: try {
438: NetworkServerControl server = new NetworkServerControl(
439: InetAddress.getByName(hostName), portNumber);
440: server.shutdown();
441: Thread.sleep(5000);
442: } catch (Exception e) {
443: System.out
444: .println(" Exception thrown while trying to shutdown the remote server.");
445: System.out.println(" " + e.getMessage());
446: passed = false;
447: }
448: serverProcess.destroy();
449: } // end of stopServer
450:
451: private static boolean checkLog(String logFileName,
452: String[] expected) throws IOException {
453: boolean allFound = true;
454: boolean[] found = new boolean[expected.length];
455: FileInputStream is = new FileInputStream(logFileName);
456: BufferedReader br = new BufferedReader(
457: new InputStreamReader(is));
458: String logLine;
459: while ((logLine = br.readLine()) != null) {
460: for (int i = 0; i < expected.length; i++) {
461: if ((!found[i]) && logLine.indexOf(expected[i]) >= 0)
462: found[i] = true;
463: }
464: }
465: for (int i = 0; i < expected.length; i++) {
466: if (!found[i]) {
467: passed = false;
468: System.out.println("Derby.log does not contain\n '"
469: + expected[i] + "'.");
470: allFound = false;
471: }
472: }
473: return allFound;
474: } // end of checkLog
475:
476: private static boolean startTest(String[] properties) {
477: announceTest();
478: return runTest(properties);
479: }
480:
481: private static boolean runTest(String[] properties) {
482: drdaConn = null;
483: embeddedConn = null;
484:
485: if (!writeDerbyProperties(properties))
486: return false;
487:
488: deleteDir(homeDir + File.separatorChar + databaseName);
489: try {
490: System.setOut(serverOutputOut);
491: Class.forName("org.apache.derby.jdbc.EmbeddedDriver")
492: .newInstance();
493: embeddedConn = DriverManager.getConnection("jdbc:derby:"
494: + databaseName + ";create=true");
495: System.setOut(realSystemOut);
496: } catch (SQLException sqle) {
497: System.setOut(realSystemOut);
498: passed = false;
499: System.out
500: .println(" Could not create an embedded database.");
501: System.out.println(" " + sqle.getMessage());
502: return false;
503: } catch (Exception e) {
504: System.setOut(realSystemOut);
505: passed = false;
506: System.out
507: .println(" Could not start the Derby client driver.");
508: System.out.println(" " + e.getMessage());
509: return false;
510: }
511:
512: if (portNumber > 0) {
513: for (int ntries = 1;; ntries++) {
514: try {
515: Thread.sleep(1000); // Give the server more time to start
516: } catch (InterruptedException ie) {
517: }
518: try {
519: drdaConn = DriverManager.getConnection(TestUtil
520: .getJdbcUrlPrefix(hostName, portNumber)
521: + databaseName, authenticationProperties);
522: break;
523: } catch (SQLException sqle) {
524: if (ntries > 5) {
525: passed = false;
526: System.out
527: .println(" Could not access database through the network server.");
528: System.out.println(" " + sqle.getMessage());
529: return false;
530: }
531: }
532: }
533: }
534: return true;
535: } // end of startTest
536:
537: private static boolean writeDerbyProperties(String[] properties) {
538: derbyPropertiesFile.delete();
539: try {
540: derbyPropertiesFile.createNewFile();
541: PrintStream propertyWriter = new PrintStream(
542: new FileOutputStream(derbyPropertiesFile));
543: propertyWriter.print(basePropertiesSB.toString());
544: for (int i = 0; i < properties.length - 1; i += 2)
545: propertyWriter.println(properties[i] + "="
546: + properties[i + 1]);
547:
548: propertyWriter.close();
549: return true;
550: } catch (IOException ioe) {
551: passed = false;
552: System.out.println(" Could not create derby.properties: "
553: + ioe.getMessage());
554: return false;
555: }
556: } // end of writeDerbyProperties
557:
558: private static void deleteDir(String dirName) {
559: deleteDir(new File(dirName));
560: }
561:
562: private static void deleteDir(File parent) {
563: if (!parent.exists())
564: return;
565: if (parent.isDirectory()) {
566: String[] child = parent.list();
567: for (int i = 0; i < child.length; i++)
568: deleteDir(new File(parent, child[i]));
569: }
570: parent.delete();
571: }
572:
573: private static void announceTest() {
574: testNumber++;
575: System.out.println("Starting test case " + testNumber + ".");
576: databaseName = "database" + testNumber;
577: }
578:
579: private static void endTest(boolean autoStarted) {
580: try {
581: if (drdaConn != null) {
582: drdaConn.close();
583: drdaConn = null;
584: }
585: if (embeddedConn != null) {
586: embeddedConn.close();
587: embeddedConn = null;
588: }
589: } catch (SQLException sqle) {
590: passed = false;
591: System.out.println(" Connection close failed:");
592: System.out.println(" " + sqle.getMessage());
593: }
594: // DERBY-803: Give the server threads time to finish their close
595: // operations before we shut down the engine. Otherwise, we might get
596: // some (harmless) error messages printed to the console. See also
597: // DERBY-1020.
598: try {
599: Thread.sleep(5000);
600: } catch (InterruptedException ex) {
601: }
602: try {
603: DriverManager.getConnection("jdbc:derby:;shutdown=true");
604: } catch (SQLException sqle) {
605: if (!sqle.getSQLState().equals("XJ015")) {
606: passed = false;
607: System.out.println(" System shutdown failed:");
608: System.out.println(" " + sqle.getMessage());
609: }
610: }
611: serverOutputOut.flush();
612: if (serverOutputBOS.size() > 0) {
613: passed = false;
614: System.out
615: .println("The auto-started server wrote to System.out.");
616: }
617: serverOutputBOS.reset();
618: if (autoStarted && databaseName != null) {
619: try {
620: // Give the server thread time to shutdown, then check that it has done so.
621: try {
622: Thread.sleep(500);
623: } catch (InterruptedException ie) {
624: }
625: ;
626: drdaConn = DriverManager.getConnection(TestUtil
627: .getJdbcUrlPrefix(hostName, portNumber)
628: + databaseName, authenticationProperties);
629: passed = false;
630: System.out
631: .println("Was able to connect to the network server after Derby shut down.");
632: drdaConn.close();
633: drdaConn = null;
634: } catch (SQLException sqle) {
635: }
636: ;
637: }
638: } // end of endTest
639:
640: private static boolean isServerStarted(NetworkServerControl server) {
641: try {
642: server.ping();
643: } catch (Exception e) {
644: return false;
645: }
646: return true;
647: }
648: }
|