001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.harness.FileCompare
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.harness;
023:
024: /***
025: * FileCompare.java
026: *
027: * Compare two files using SimpleDiff
028: * Purpose: simulate diff
029: * Note: if usesysdiff=true, we execute the system's diff
030: ***/
031:
032: import java.io.*;
033: import java.lang.reflect.*;
034: import java.util.StringTokenizer;
035: import java.util.Properties;
036:
037: public class FileCompare {
038:
039: private String testBase;
040: private String framework;
041: private String jvmName;
042: private String jvmString;
043: private String serverJvm;
044: private int iminor;
045: private boolean searchJdk12 = false;
046: private boolean searchJdk13 = false;
047: private boolean searchJdk14 = false;
048: private int driverVersionMajor = 0;
049: private int driverVersionMinor = 0;
050: private boolean searchFrame;
051: private boolean searchDriverVersion;
052: private InputStream master = null;
053: private boolean verbose;
054:
055: public FileCompare() {
056: verbose = Boolean.getBoolean("verbose");
057: }
058:
059: // The arguments should be the names of the input and output files
060: public boolean exec(String outfile, File outDir,
061: PrintWriter pwDiff, String testBaseOrig, String framework,
062: String jvmName, int iminor, boolean useprocess,
063: boolean usesysdiff, String canondir, String canonpath,
064: String serverJvm) throws IOException,
065: ClassNotFoundException {
066: testBase = testBaseOrig;
067: this .framework = framework;
068: this .jvmName = jvmName;
069: this .iminor = iminor;
070: this .jvmString = jvmName;
071: this .serverJvm = serverJvm;
072:
073: BufferedReader outFile;
074: BufferedReader masterFile;
075: StringBuffer sb = new StringBuffer();
076:
077: // If framework is DerbyNet, we may need to check subdirs of the master canon dir
078: // for specific masters by client we're running against. So, get version
079: // for later use if that is the case.
080: if (framework.startsWith("DerbyNet")) {
081: Class c = null;
082: Method m = null;
083: Object o = null;
084: Integer i = null;
085: try {
086: c = Class.forName(NetServer.getDriverName(framework));
087: o = c.newInstance();
088: m = c.getMethod("getMajorVersion", null);
089: i = (Integer) m.invoke(o, null);
090: driverVersionMajor = i.intValue();
091: m = c.getMethod("getMinorVersion", null);
092: i = (Integer) m.invoke(o, null);
093: driverVersionMinor = i.intValue();
094: if (framework.startsWith("DerbyNet"))
095: searchDriverVersion = true;
096: } catch (Exception e) {
097: //if anything goes wrong, make sure the driver version values are set to zero
098: //forget about it.
099:
100: System.out.println("Cannot determine driver version:"
101: + e);
102: driverVersionMinor = 0;
103: driverVersionMajor = 0;
104: searchDriverVersion = false;
105: }
106: }
107:
108: // The outfile name is known -- outfile
109: // But the master canon needs to be located
110: // The user can set canondir (or it defaults to "master")
111: String topdir = "";
112: if ((canondir != null) && (canondir.length() > 0))
113: topdir = canondir;
114: else {
115: // if this is using product jars, use product_master first
116: Class c = FileCompare.class; // get our class loader
117: InputStream is = c
118: .getResourceAsStream("/org/apache/derby/info/DBMS.properties");
119: Properties dbprop = new Properties();
120: dbprop.load(is);
121: is.close();
122:
123: String filename = dbprop.getProperty("derby.product.file");
124: if (filename != null) {
125: //looks like it might be one of our jars?
126: if (filename.startsWith("derby")
127: && filename.endsWith(".jar")) {
128: canondir = "product_master"; // remember redirection
129: topdir = "product_master";
130: } else
131: topdir = "master";
132: } else
133: topdir = "master";
134: }
135:
136: // There can be subdirs under the master for framework, jvm
137: String subdir = "";
138: boolean searchDefault = true; // if no framework or special jvm
139: boolean searchBoth = false;
140: boolean searchJvm = false;
141: if ((framework != null) && (framework.length() > 0)) {
142: searchFrame = true;
143: subdir = framework;
144: }
145: if ((jvmName != null) && (jvmName.length() > 0)
146: & (!jvmName.equals("currentjvm"))) {
147: searchJvm = true;
148: if (searchFrame)
149: searchBoth = true;
150: if (iminor >= 2) // jdk12 or higher may use jdk12 masters
151: jvmString = "jdk12";
152: if (iminor >= 2)
153: searchJdk12 = true;
154: if (iminor >= 3)
155: searchJdk13 = true;
156: if (iminor >= 4)
157: searchJdk14 = true;
158: subdir += jvmName;
159: }
160:
161: if (searchFrame || searchJvm || searchBoth)
162: searchDefault = false;
163:
164: sb.append(topdir);
165: if (subdir.length() > 0)
166: sb.append(subdir + '/');
167: sb.append(testBase + ".out");
168: String masterfilename = sb.toString();
169:
170: InputStream is = null;
171:
172: // Now try to locate the master file
173:
174: if (is == null) {
175: searchCanondir(topdir);
176: is = master;
177: }
178:
179: // If the master is still not found, create an empty master
180: if (is == null) {
181: is = new ByteArrayInputStream(new byte[] {});
182: }
183: // compress blanks in output columns to make up for column width differences
184: // for JCC output
185: if (NetServer.isClientConnection(framework)) {
186: try {
187: Sed sed = new Sed();
188: File JCCOutFile = new File(outDir, testBase
189: + ".tmpmstr");
190: sed.execJCC(is, JCCOutFile);
191: is = new FileInputStream(JCCOutFile);
192: } catch (ClassFormatError cfe) {
193: System.out.println("SED Error: " + cfe.getMessage());
194: }
195: } else {
196: // read in in fixed format, but write out relying on default encoding
197: File EncodedOutFile = new File(outDir, testBase
198: + ".tmpmstr");
199: BufferedReader inFile = new BufferedReader(
200: new InputStreamReader(is, "UTF-8"));
201:
202: PrintWriter pw = new PrintWriter(new BufferedWriter(
203: new FileWriter(EncodedOutFile), 10000), true);
204: int c;
205: while ((c = inFile.read()) != -1)
206: pw.write(c);
207: pw.flush();
208: pw.close();
209: is = new FileInputStream(EncodedOutFile);
210: }
211:
212: // Define the input and output files
213: outFile = new BufferedReader(new FileReader(outfile));
214: masterFile = new BufferedReader(new InputStreamReader(is));
215:
216: // Do the comparison (diff)
217: if (usesysdiff == true)
218: return doSysDiff(is, testBase, outfile, outDir, pwDiff);
219: else {
220: return doDiff2(outFile, masterFile, pwDiff);
221: }
222: }
223:
224: public boolean doDiff2(BufferedReader outFile,
225: BufferedReader masterFile, PrintWriter pwDiff)
226: throws IOException {
227: return ((new SimpleDiff()).doWork(masterFile, outFile, pwDiff));
228: }
229:
230: public boolean doSysDiff(InputStream masterIS, String testBase,
231: String outfile, File outDir, PrintWriter pwDiff)
232: throws IOException {
233: // Create a temp file to copy the master (located as an InputStream)
234: BufferedReader in = new BufferedReader(new InputStreamReader(
235: masterIS));
236: File tempMaster = new File((new File(outDir, testBase
237: + ".master")).getCanonicalPath());
238:
239: // Create a PrintWriter for copying the master temporarily for the diff
240: PrintWriter pwMaster = new PrintWriter(new BufferedWriter(
241: new FileWriter(tempMaster.getPath()), 10000), true);
242: String str = "";
243: while ((str = in.readLine()) != null) {
244: pwMaster.println(str);
245: }
246: pwMaster.close();
247: pwMaster = null;
248: in = null;
249:
250: String diffs = "0";
251: // Now create a process and do the system diff, capture to .out
252: Process pr = null;
253: try {
254: StringBuffer sb = new StringBuffer();
255: sb.append("diff ");
256: sb.append(tempMaster.getCanonicalPath());
257: sb.append(" ");
258: sb.append(outfile);
259: String diffCmd = sb.toString();
260:
261: //System.out.println("diffCmd = " + diffCmd);
262:
263: pr = Runtime.getRuntime().exec(diffCmd);
264:
265: // We need the process inputstream to capture into the diff file
266: //System.out.println("Capture the process InputStream...");
267: BackgroundStreamDrainer stdout = new BackgroundStreamDrainer(
268: pr.getInputStream(), null);
269: BackgroundStreamDrainer stderr = new BackgroundStreamDrainer(
270: pr.getErrorStream(), null);
271:
272: pr.waitFor();
273: String result = HandleResult.handleResult(pr.exitValue(),
274: stdout.getData(), stderr.getData(), pwDiff);
275: diffs = result.substring(result.lastIndexOf(',') + 1);
276: //System.out.println("diffs: " + diffs);
277: pr.destroy();
278: pr = null;
279: } catch (Throwable t) {
280: System.out.println("Process exception: " + t);
281: if (pr != null) {
282: pr.destroy();
283: pr = null;
284: }
285: }
286: tempMaster.delete();
287: if (diffs.equals("0"))
288: return false;
289: else
290: return true;
291: }
292:
293: public boolean doDiff(BufferedReader outFile,
294: BufferedReader masterFile, PrintWriter pwDiff)
295: throws IOException {
296: String str1;
297: String str2;
298: boolean diff = false;
299:
300: int line = 0;
301: int diffnum = 0;
302: int diffline = 0;
303: while ((str1 = outFile.readLine()) != null) {
304: line++;
305: str1 = str1.trim();
306: //System.out.println("Reading line: " + line);
307: // Read the line from the master file and compare
308: if ((str2 = masterFile.readLine()) != null) {
309: str2 = str2.trim();
310: if (!str1.equals(str2)) {
311: // Some lines diff because of too many spaces
312: StringBuffer sb1 = new StringBuffer();
313: StringBuffer sb2 = new StringBuffer();
314: StringTokenizer st1 = new StringTokenizer(str1);
315: while (st1.hasMoreTokens()) {
316: sb1.append(st1.nextToken());
317: }
318: //System.out.println("Out line: " + sb1.toString());
319:
320: StringTokenizer st2 = new StringTokenizer(str2);
321: while (st2.hasMoreTokens()) {
322: sb2.append(st2.nextToken());
323: }
324: //System.out.println("Master line: " + sb2.toString());
325:
326: if (sb1.toString().equals(sb2.toString()))
327: diff = false;
328: // If the two lines are dashes, but wrong #, just ignore
329: else if ((str1.startsWith("-----"))
330: && (str1.endsWith("-----"))) {
331: if ((str2.startsWith("-----"))
332: && (str2.endsWith("-----")))
333: diff = false;
334: } else {
335: diff = true;
336: diffnum++;
337: System.out.println("Diff occurred at line: "
338: + line);
339: pwDiff.println("Diff occurred at line: "
340: + line);
341: pwDiff.flush();
342: break;
343: }
344: } else {
345: diff = false;
346: }
347: }
348: } // end while
349: outFile.close();
350: masterFile.close();
351: return diff;
352: }// end exec
353:
354: private void searchCanondir(String canondir) {
355: String prefix = canondir + '/';
356: if (master == null && searchFrame)
357: searchFramework(prefix);
358: if (master == null)
359: searchJvm(prefix);
360: if (master == null && searchDriverVersion)
361: searchDriverVersion(prefix);
362: if (master == null)
363: getmaster(prefix);
364: if (master == null && canondir != "master")
365: searchCanondir("master");
366: }
367:
368: private void searchJvm(String prefix) {
369: // The JVM search follows the following pattern, with one exception:
370: // first search jvmName (to support unnamed/non-IBM or Sun JVMs)
371: // if vendor == IBM, search ibm+rev then jdk+rev, decrementing rev by one until rev=13,
372: // in each dir, search framework and driver version if applicable.
373: // BUT, if it's j9, first j9_foundation, then search j9_22 for 22, otherwise, j9_13 then
374: // the normal ibm13 search pattern: ibm13 then jdk13.
375:
376: String newprefix;
377: if (jvmName.startsWith("j9")
378: || (serverJvm != null && serverJvm.startsWith("j9"))) {
379: if (jvmName.startsWith("j9_foundation")) {
380: newprefix = prefix + "j9_foundation" + '/';
381: if (master == null && searchDriverVersion)
382: searchDriverVersion(newprefix);
383: if (master == null)
384: getmaster(newprefix);
385: } else {
386: newprefix = prefix + jvmName + '/';
387: if ((!jvmName.equals("j9_13")) && (iminor > 1)) {
388: for (int i = iminor; i > 1; i--) {
389: if (master == null) {
390: newprefix = prefix + "j9_2" + i + '/';
391: getmaster(newprefix);
392: }
393: }
394: }
395: if (master == null)
396: newprefix = prefix + "j9_13" + '/';
397: }
398: if (master == null && searchDriverVersion)
399: searchDriverVersion(newprefix);
400: if (master == null)
401: getmaster(newprefix);
402:
403: }
404: for (int i = iminor; i >= 2; i--) {
405: if (jvmName.startsWith("ibm")) {
406: newprefix = prefix + "ibm1" + i + '/';
407: if (master == null && searchDriverVersion)
408: searchDriverVersion(newprefix);
409: if (master == null)
410: getmaster(newprefix);
411: }
412: newprefix = prefix + "jdk1" + i + '/';
413: if (master == null && searchDriverVersion)
414: searchDriverVersion(newprefix);
415: if (master == null)
416: getmaster(newprefix);
417: }
418: }
419:
420: private void searchFramework(String prefix) {
421: String newprefix;
422: newprefix = prefix + framework + '/';
423: if (master == null)
424: searchJvm(newprefix);
425: if (master == null && searchDriverVersion)
426: searchDriverVersion(newprefix);
427: if (master == null)
428: getmaster(newprefix);
429: }
430:
431: private void searchDriverVersion(String prefix) {
432: // It is not sufficient to simply search the current driver version.
433: // We must search down through the versions to find the newest applicable master.
434:
435: String newprefix;
436:
437: for (int j = ((driverVersionMajor * 10) + driverVersionMinor); j >= 10; j--) {
438: newprefix = prefix + "ver" + j / 10 + "." + j % 10 + '/';
439: if (master == null)
440: getmaster(newprefix);
441: }
442: }
443:
444: private void getmaster(String prefix) {
445: String fullname = prefix + testBase + ".out";
446: master = RunTest.loadTestResource(fullname);
447: if (master != null)
448: if (verbose)
449: System.out.println("MasterFileName = " + fullname);
450: }
451: }
|