001: /**
002: * TestDataGeneration.java
003: * TestGen4J is licensed under Open Software License 2.1
004: * For details, please refer to:
005: * http://www.opensource.org/licenses/osl-2.1.php
006: */package com.spikesource.spiketestgen;
007:
008: import java.io.BufferedWriter;
009: import java.io.File;
010: import java.io.FileWriter;
011: import java.io.IOException;
012: import java.util.StringTokenizer;
013:
014: /**
015: * Generates the XML data file for the test cases. The XML file
016: * generated has the actual test cases to be executed. A rules file,
017: * an another XML file, has boundary conditions for primitive data
018: * types. This file is parsed and according to the rules for each
019: * attribute as a data type, all possible combinations of the test
020: * cases are generated.
021: *
022: * @version 0.1.4-alpha
023: * @author Manish Marathe
024: */
025: public class TestDataGeneration {
026: /**
027: * Main method of the class.
028: *
029: * @param args
030: * Command line parameters.
031: */
032: public static void main(final String[] args) {
033: }
034:
035: /**
036: * Creates the top, common block of the XML data file.
037: *
038: * @param outputDIR
039: * The output directory where data file is created.
040: * @return
041: * Returns the name of the created file.
042: */
043: public final String createXMLDataFile(final String outputDIR) {
044: String xmlFileName = "data.xml";
045:
046: File handle = new File(outputDIR, xmlFileName);
047:
048: if (handle.exists()) {
049: handle.delete();
050: }
051:
052: try {
053: BufferedWriter out = new BufferedWriter(new FileWriter(
054: handle, true));
055: out.write("<?xml version =\"1.0\" encoding = \"UTF-8\"?>");
056: out.newLine();
057: out.write(" <tests xmlns:xsi=\"http://www.w3.org/"
058: + "2001/XMLSchema-instance\"");
059: out.newLine();
060: out.write(" xsi:noNamespaceSchemaLocation=\"/usr/bin/"
061: + "jtestcase-2.2.0/config/jtestcase.xsd\">");
062: out.newLine();
063: out.flush();
064: out.close();
065: } catch (IOException e) {
066: e.printStackTrace();
067: }
068:
069: return xmlFileName;
070: }
071:
072: /**
073: * Writes Class details,viz., name of the class, any global
074: * parameters, to the data file.
075: *
076: * @param classname
077: * name of the original class under test
078: * @param outputDIR
079: * name of the output directory
080: * @param filename
081: * name of the XML data file
082: */
083: public final void writeClassDetailsToXMLDataFile(
084: final String classname, final String outputDIR,
085: final String filename) {
086:
087: String className = classname;
088: className = className + "Test";
089:
090: File handle = new File(outputDIR, filename);
091:
092: try {
093: BufferedWriter out = new BufferedWriter(new FileWriter(
094: handle, true));
095: out.write(" <class name=\"" + className + "\">");
096: out.newLine();
097: out.write(" <!-- global params -->");
098: out.newLine();
099: out.write(" <params>");
100:
101: /* Global parameters will go go. I am not writing them right now.*/
102: out.write(" </params>");
103: out.newLine();
104: out.flush();
105: out.close();
106: } catch (IOException e) {
107: e.printStackTrace();
108: }
109: }
110:
111: /**
112: * This is the main method of this class. This method looks for the
113: * type of parameters of the method under test and according to the
114: * type retrieves the rules for those types from the rules file. All
115: * possible combinations of the rules of all parameters forms the unit test
116: * case data.
117: *
118: * @param methodName
119: * Original name of the method under test.
120: * @param methodReturnType
121: * Return type of the method under test.
122: * @param methodParams
123: * All Parameters of the method under test.
124: * @param numOfParams
125: * Total number of parameters of the method in test.
126: * @param outputDIR
127: * The output directory.
128: * @param filename
129: * XML data file name.
130: * @throws IOException
131: * Throws IOException.
132: */
133: public final void writeMethodDetailsToXMLDataFile(
134: final String methodName, final String methodReturnType,
135: final String[] methodParams, final int numOfParams,
136: final String outputDIR, final String filename)
137: throws IOException {
138:
139: int k = 0;
140: int tempCount = 0;
141: int maxCount = 0;
142: int getThisCount = 0;
143: int u = 1;
144: boolean setBreakingCondition = false;
145: int[] arrayCount = new int[numOfParams];
146: int[] flag = new int[numOfParams];
147: String this Combination = null;
148: String name = methodName;
149:
150: String nameTmp = name.charAt(0) + "";
151: nameTmp.trim();
152: name = "test" + nameTmp.toUpperCase() + name.substring(1);
153:
154: File handle = new File(outputDIR, filename);
155:
156: for (int x = 0; x < numOfParams; x++) {
157: StringTokenizer temp = new StringTokenizer(methodParams[x],
158: ",");
159: tempCount = temp.countTokens();
160:
161: if (maxCount < tempCount) {
162: maxCount = tempCount;
163: }
164: }
165:
166: Object[][] paramConditions = new Object[numOfParams][maxCount];
167:
168: if ((maxCount > 1) && (numOfParams > 1)) {
169: for (int p = 0; p < numOfParams; p++) {
170: for (int q = 0; q < maxCount; q++) {
171: paramConditions[p][q] = "NOTFILLED";
172: }
173: }
174:
175: for (int i = 0; i < numOfParams; i++) {
176: StringTokenizer paramDetails = new StringTokenizer(
177: methodParams[i], ",");
178: k = paramDetails.countTokens();
179:
180: for (int j = 0; j < k; j++) {
181: paramConditions[i][j] = (Object) paramDetails
182: .nextToken();
183: }
184: } //End For
185:
186: for (int tmpvar = 0; tmpvar < numOfParams; tmpvar++) {
187: arrayCount[tmpvar] = 1;
188: flag[tmpvar] = 0;
189: }
190:
191: BufferedWriter out = new BufferedWriter(new FileWriter(
192: handle, true));
193:
194: while (!setBreakingCondition) {
195: /* Combination of the test data happens here.*/
196: for (int m = 1; m < paramConditions[0].length; m++) {
197: this Combination = paramConditions[0][m] + ",";
198: for (int somevar = 1; somevar < numOfParams; somevar++) {
199: if (somevar < (numOfParams - 1)) {
200: this Combination = this Combination
201: + paramConditions[somevar][arrayCount[somevar]]
202: + ",";
203: } else if (somevar == (numOfParams - 1)) {
204: this Combination = this Combination
205: + paramConditions[somevar][arrayCount[somevar]];
206: }
207: }
208: this Permutation1(out, paramConditions,
209: this Combination, name, methodReturnType,
210: numOfParams);
211: //if was here
212: }
213:
214: /* End of Combination*/
215: /* Set flags for arrayCount here */
216: for (u = 1; u < numOfParams; u++) {
217: if ((arrayCount[u] == (maxCount - 1))) {
218: flag[u] = 1;
219: }
220: }
221:
222: /*Set flags ends here */
223: /* Just check flags, process flagIncrementNextCounter */
224: for (int flagcnt = 1; flagcnt < numOfParams; flagcnt++) {
225: for (int flagCheck = 1; flagCheck < (flagcnt + 1); flagCheck++) {
226: if (flag[flagCheck] != 1) {
227: break;
228: } else if (flag[flagCheck] == 1) {
229: getThisCount = flagCheck;
230: }
231: }
232: }
233:
234: /* End processing flagIncrementNextCounter */
235: /* Start arrayCount Incrementation */
236: for (int flagcnt = 1; flagcnt < numOfParams; flagcnt++) {
237: if (getThisCount == (numOfParams - 1)) {
238: setBreakingCondition = true;
239: }
240:
241: if (flagcnt == 1) {
242: arrayCount[flagcnt] = (arrayCount[flagcnt] + 1)
243: % (maxCount - 1);
244:
245: if (arrayCount[flagcnt] == 0) {
246: arrayCount[flagcnt] = (maxCount - 1);
247: }
248: }
249:
250: if (flagcnt < (getThisCount + 1)) {
251: if (flagcnt < (numOfParams - 1)) {
252: if ((arrayCount[(flagcnt + 1) % numOfParams]) == (maxCount - 1)) {
253: arrayCount[(flagcnt + 1) % numOfParams] = (arrayCount[(flagcnt + 1)
254: % numOfParams] + 1)
255: % (maxCount - 1);
256: } else {
257: arrayCount[(flagcnt + 1) % numOfParams]++;
258: }
259: } else if (flagcnt == (numOfParams - 1)) {
260: System.out.println("Done");
261: }
262:
263: flag[flagcnt] = 0;
264: }
265: }
266: /* End arrayCount incrementation */
267: getThisCount = 0;
268: } //End While
269: out.close();
270: } else if ((maxCount > 1) && (numOfParams == 1)) { //End if (maxCount>2)
271:
272: StringTokenizer temp = new StringTokenizer(methodParams[0],
273: ",");
274: int numOfConditions = temp.countTokens();
275:
276: for (int i = 0; i < numOfConditions; i++) {
277: paramConditions[0][i] = temp.nextToken();
278: }
279:
280: BufferedWriter out = new BufferedWriter(new FileWriter(
281: handle, true));
282: this Permutation2(out, paramConditions, name,
283: methodReturnType, numOfConditions, numOfParams);
284: out.close();
285: } // End else if((maxCount>2)&&(numOfParams==1))
286: }
287:
288: /**
289: * The method writes the test cases in the data file for the
290: * orginal methods having more than one argument.
291: *
292: * @param out
293: * BufferedWriter Object.
294: * @param paramConditions
295: * Boundary condition of arguments.
296: * @param thisCombination
297: * Current combination of the values
298: * of the arguments set in the rules.xml
299: * file.
300: * @param name
301: * Test method name.
302: * @param methodReturnType
303: * Return type of the method.
304: * @param numOfParams
305: * No. of arguments.
306: * @throws IOException
307: * Throws IOException.
308: */
309: public final void this Permutation1(final BufferedWriter out,
310: final Object[][] paramConditions,
311: final String this Combination, final String name,
312: final String methodReturnType, final int numOfParams)
313: throws IOException {
314:
315: int paramNumber = 0;
316: int caseNumber = 0;
317: String varNumber = null;
318:
319: if (this Combination.indexOf("NOTFILLED") == -1) {
320: caseNumber++;
321:
322: StringTokenizer boundaryConditions = new StringTokenizer(
323: this Combination, ",");
324:
325: out.write(" <method name=\"" + name
326: + "\" test-case=\"" + caseNumber + "\">");
327: out.newLine();
328: out.write(" <params>");
329: out.newLine();
330:
331: for (int param = 0; param < numOfParams; param++) {
332: paramNumber++;
333: varNumber = "var" + (param + 1);
334:
335: String prm = "<param name=\"" + varNumber
336: + "\" type=\"" + paramConditions[param][0]
337: + "\">" + boundaryConditions.nextToken()
338: + "</param>";
339: out.write(" " + prm);
340: out.newLine();
341: }
342:
343: paramNumber = 0;
344: out.write(" </params>");
345: out.newLine();
346: out.write(" <asserts>");
347: out.newLine();
348: out.write(" <assertgroup name"
349: + "=\"testResult\">");
350: out.newLine();
351:
352: if (methodReturnType.equals("int")) {
353: out.write(" <assert name="
354: + "\"testResult1\" type=\"" + methodReturnType
355: + "\" action=\"NOTLT\">-2147483648</assert>");
356: out.newLine();
357: out.write(" <assert name="
358: + "\"testResult2\" type=\"" + methodReturnType
359: + "\" action=\"NOTGT\">2147483647</assert>");
360: out.newLine();
361: } else if (methodReturnType.equals("short")) {
362: out.write(" <assert name="
363: + "\"testResult1\" type=\"" + methodReturnType
364: + "\" action=\"NOTLT\">-32768</assert>");
365: out.newLine();
366: out.write(" <assert name="
367: + "\"testResult2\" type=\"" + methodReturnType
368: + "\" action=\"NOTGT\">32767</assert>");
369: out.newLine();
370: } else if (methodReturnType.equals("float")) {
371: out.write(" <assert name="
372: + "\"testResult1\" type=\"" + methodReturnType
373: + "\" action=\"NOTLT\">1.4E-45</assert>");
374: out.newLine();
375: out.write(" <assert name="
376: + "\"testResult2\" type=\"" + methodReturnType
377: + "\" action=\"NOTGT\">3.4028235E+38</assert>");
378: out.newLine();
379: } else if (methodReturnType.equals("long")) {
380: out.write(" <assert name="
381: + "\"testResult1\" type=\"" + methodReturnType
382: + "\" action=\"NOTLT\">-9223372036854775808"
383: + "</assert>");
384: out.newLine();
385: out.write(" <assert name="
386: + "\"testResult2\" type=\"" + methodReturnType
387: + "\" action=\"NOTGT\">9223372036854775807"
388: + "</assert>");
389: out.newLine();
390: } else if (methodReturnType.equals("double")) {
391: out.write(" <assert name="
392: + "\"testResult1\" type=\"" + methodReturnType
393: + "\" action=\"NOTLT\">4.9E-324</assert>");
394: out.newLine();
395: out.write(" <assert name="
396: + "\"testResult2\" type=\"" + methodReturnType
397: + "\" action=\"NOTGT\">1.7976931348623157E+308"
398: + "</assert>");
399: out.newLine();
400: } else if (methodReturnType.equals("String")) {
401: out.write(" <assert name="
402: + "\"testResult1\" type=\"" + methodReturnType
403: + "\" action=\"NOTEQUALS\">null</assert>");
404: out.newLine();
405: out.write(" <assert name="
406: + "\"testResult2\" type=\"" + methodReturnType
407: + "\" action=\"NOTEQUALS\">\"\"</assert>");
408: out.newLine();
409: out.write(" <assert name="
410: + "\"testResult3\" type=\"" + methodReturnType
411: + "\" action=\"NOTEQUALS\">\" \"</assert>");
412: out.newLine();
413: } else if (methodReturnType.equals("char")) {
414: out.write(" <assert name="
415: + "\"testResult1\" type=\"" + methodReturnType
416: + "\" action=\"NOTLT\">0</assert>");
417: out.newLine();
418: out.write(" <assert name="
419: + "\"testResult2\" type=\"" + methodReturnType
420: + "\" action=\"NOTGT\">9</assert>");
421: out.newLine();
422: out.write(" <assert name="
423: + "\"testResult3\" type=\"" + methodReturnType
424: + "\" action=\"NOTEQUALS\">'\0'</assert>");
425: out.newLine();
426: out.write(" <assert name="
427: + "\"testResult4\" type=\"" + methodReturnType
428: + "\" action=\"NOTEQUALS\">''</assert>");
429: out.newLine();
430: out.write(" <assert name="
431: + "\"testResult5\" type=\"" + methodReturnType
432: + "\" action=\"NOTEQUALS\">' '</assert>");
433: out.newLine();
434: } else if (methodReturnType.equals("void")) {
435: out.write(" <assert name="
436: + "\"testResult1\" type=\"" + methodReturnType
437: + "\" action=\"EQUALS\">null</assert>");
438: out.newLine();
439: } else {
440: out.write(" <assert name="
441: + "\"testResult1\" type=\"" + methodReturnType
442: + "\" action=\"NOTEQUALS\">null</assert>");
443: out.newLine();
444: }
445:
446: out.write(" </assertgroup>");
447: out.newLine();
448: out.write(" </asserts>");
449: out.newLine();
450: out.write(" <exception>java.lang."
451: + "NullPointerException</exception>");
452: out.newLine();
453: out.write(" </method>");
454: out.newLine();
455: out.flush();
456: }
457: }
458:
459: /**
460: * The method writes the test cases in the data file for the
461: * orginal methods having more than one argument.
462: *
463: * @param out
464: * BufferedWriter Object.
465: * @param paramConditions
466: * Boundary condition of arguments.
467: * @param name
468: * Test method name.
469: * @param methodReturnType
470: * Return type of the method.
471: * @param numOfConditions
472: * Total number of boundary conditions
473: * for the data type of the argument.
474: * @param numOfParams
475: * No. of arguments.
476: * @throws IOException
477: * Throws IOException.
478: */
479: public final void this Permutation2(final BufferedWriter out,
480: final Object[][] paramConditions, final String name,
481: final String methodReturnType, final int numOfConditions,
482: final int numOfParams) throws IOException {
483:
484: for (int i = 1; i < numOfConditions; i++) {
485: //varNumber = "var" + i;
486: out.write(" <method name=\"" + name
487: + "\" test-case=\"" + i + "\">");
488: out.newLine();
489: out.write(" <params>");
490: out.newLine();
491: out.write(" <param name=\"var1\" type=\""
492: + paramConditions[0][0] + "\">"
493: + paramConditions[0][i] + "</param>");
494: out.newLine();
495: out.write(" </params>");
496: out.newLine();
497: out.write(" <asserts>");
498: out.newLine();
499: out.write(" <assertgroup name="
500: + "\"testResult\">");
501: out.newLine();
502:
503: if (methodReturnType.equals("int")) {
504: out.write(" <assert name="
505: + "\"testResult1\" type=\"" + methodReturnType
506: + "\" action=\"NOTLT\">-2147483648</assert>");
507: out.newLine();
508: out.write(" <assert name="
509: + "\"testResult2\" type=\"" + methodReturnType
510: + "\" action=\"NOTGT\">2147483647</assert>");
511: out.newLine();
512: } else if (methodReturnType.equals("short")) {
513: out.write(" <assert name="
514: + "\"testResult1\" type=\"" + methodReturnType
515: + "\" action=\"NOTLT\">-32768</assert>");
516: out.newLine();
517: out.write(" <assert name="
518: + "\"testResult2\" type=\"" + methodReturnType
519: + "\" action=\"NOTGT\">32767</assert>");
520: out.newLine();
521: } else if (methodReturnType.equals("float")) {
522: out.write(" <assert name="
523: + "\"testResult1\" type=\"" + methodReturnType
524: + "\" action=\"NOTLT\">1.4E-45</assert>");
525: out.newLine();
526: out.write(" <assert name="
527: + "\"testResult2\" type=\"" + methodReturnType
528: + "\" action=\"NOTGT\">3.4028235E+38</assert>");
529: out.newLine();
530: } else if (methodReturnType.equals("long")) {
531: out
532: .write(" <assert name="
533: + "\"testResult1\" type=\""
534: + methodReturnType
535: + "\" action=\"NOTLT\">-9223372036854775808</assert>");
536: out.newLine();
537: out
538: .write(" <assert name="
539: + "\"testResult2\" type=\""
540: + methodReturnType
541: + "\" action=\"NOTGT\">9223372036854775807</assert>");
542: out.newLine();
543: } else if (methodReturnType.equals("double")) {
544: out.write(" <assert name="
545: + "\"testResult1\" type=\"" + methodReturnType
546: + "\" action=\"NOTLT\">4.9E-324</assert>");
547: out.newLine();
548: out
549: .write(" <assert name="
550: + "\"testResult2\" type=\""
551: + methodReturnType
552: + "\" action=\"NOTGT\">1.7976931348623157E+308</assert>");
553: out.newLine();
554: } else if (methodReturnType.equals("String")) {
555: out.write(" <assert name="
556: + "\"testResult1\" type=\"" + methodReturnType
557: + "\" action=\"NOTEQUALS\">null</assert>");
558: out.newLine();
559: out.write(" <assert name="
560: + "\"testResult2\" type=\"" + methodReturnType
561: + "\" action=\"NOTEQUALS\">\"\"</assert>");
562: out.newLine();
563: out.write(" <assert name="
564: + "\"testResult3\" type=\"" + methodReturnType
565: + "\" action=\"NOTEQUALS\">\" \"</assert>");
566: out.newLine();
567: } else if (methodReturnType.equals("boolean")) {
568: out.write(" <assert name="
569: + "\"testResult1\" type=\"" + methodReturnType
570: + "\" action=\"EQUALS\">true</assert>");
571: out.newLine();
572: out.write(" <assert name="
573: + "\"testResult2\" type=\"" + methodReturnType
574: + "\" action=\"EQUALS\">false</assert>");
575: out.newLine();
576: } else if (methodReturnType.equals("char")) {
577: out.write(" <assert name="
578: + "\"testResult1\" type=\"" + methodReturnType
579: + "\" action=\"NOTLT\">0</assert>");
580: out.newLine();
581: out.write(" <assert name="
582: + "\"testResult2\" type=\"" + methodReturnType
583: + "\" action=\"NOTGT\">9</assert>");
584: out.newLine();
585: out.write(" <assert name="
586: + "\"testResult3\" type=\"" + methodReturnType
587: + "\" action=\"NOTEQUALS\">'\0'</assert>");
588: out.newLine();
589: out.write(" <assert name="
590: + "\"testResult4\" type=\"" + methodReturnType
591: + "\" action=\"NOTEQUALS\">''</assert>");
592: out.newLine();
593: out.write(" <assert name="
594: + "\"testResult5\" type=\"" + methodReturnType
595: + "\" action=\"NOTEQUALS\">' '</assert>");
596: out.newLine();
597: } else if (methodReturnType.equals("void")) {
598: out.write(" <assert name="
599: + "\"testResult1\" type=\"" + methodReturnType
600: + "\" action=\"EQUALS\">null</assert>");
601: out.newLine();
602: } else {
603: out.write(" <assert name="
604: + "\"testResult1\" type=\"" + methodReturnType
605: + "\" action=\"NOTEQUALS\">null</assert>");
606: out.newLine();
607: }
608:
609: out.write(" </assertgroup>");
610: out.newLine();
611: out.write(" </asserts>");
612: out.newLine();
613: out.write(" <exception>java.lang."
614: + "NullPointerException</exception>");
615: out.newLine();
616: out.write(" </method>");
617: out.newLine();
618: }
619: out.flush();
620: }
621:
622: /**
623: * End the class tag in the XML data file as test data for all methods
624: * of this class are written to the data file.
625: *
626: * @param outputDIR
627: * The output directory.
628: * @param filename
629: * Filename of the XML data file.
630: */
631: public final void endClassInXMLDataFile(final String outputDIR,
632: final String filename) {
633:
634: File handle = new File(outputDIR, filename);
635:
636: try {
637: BufferedWriter out = new BufferedWriter(new FileWriter(
638: handle, true));
639:
640: out.newLine();
641: out.write(" </class>");
642: out.newLine();
643: out.flush();
644: out.close();
645: } catch (IOException e) {
646: e.printStackTrace();
647: }
648: }
649:
650: /**
651: * End the <tests> tag in the XML data file, which closes the data file.
652: * </tests>
653: * @param outputDIR
654: * The output directory.
655: * @param filename
656: * name of the XML data file.
657: */
658: public final void endXMLDataFile(final String outputDIR,
659: final String filename) {
660: File handle = new File(outputDIR, filename);
661:
662: try {
663: BufferedWriter out = new BufferedWriter(new FileWriter(
664: handle, true));
665:
666: out.newLine();
667: out.write(" </tests>");
668: out.newLine();
669: out.flush();
670: out.close();
671: } catch (IOException e) {
672: e.printStackTrace();
673: }
674: }
675: }
|