1   /*
2    * jGuild Project: jRPM
3    * Released under the Apache License ( http://www.apache.org/LICENSE )
4    */
5   package com.jguild.jrpm.test;
6   
7   import java.io.ByteArrayOutputStream;
8   import java.io.File;
9   import java.io.IOException;
10  import java.io.OutputStream;
11  import java.net.URL;
12  import java.util.StringTokenizer;
13  
14  import junit.framework.TestCase;
15  
16  import org.apache.log4j.ConsoleAppender;
17  import org.apache.log4j.Logger;
18  import org.apache.log4j.SimpleLayout;
19  
20  import com.jguild.jrpm.io.RPMFile;
21  import com.jguild.jrpm.io.constant.EnumIf;
22  import com.jguild.jrpm.io.constant.RPMHeaderTag;
23  import com.jguild.jrpm.io.datatype.DataTypeIf;
24  
25  /***
26   * Test case to compare jRPM against an installed instance of rpm.
27   * 
28   * @author kuss @warn For this test to work you need rpm installed on your
29   *         system.
30   */
31  public class NativeRPMTest extends TestCase {
32  
33      private static final Logger logger = Logger
34              .getLogger(RPMFileParsingTest.class);
35  
36      private static final String RPM_FILE = "ElectricFence-2.2.2-15.i386.rpm";
37  
38      /***
39       * Test if all tag names are supported by jRPM. The tags will be querried
40       * from a installed instance of rpm with the option --querytags. Than all
41       * tags are compared to the tags defined in jRPM.
42       * 
43       * @throws IOException
44       *            if an io error occur @warn For this test to work you need rpm
45       *            installed on your system.
46       */
47      public void testKnownTypes() throws IOException {
48          String originTypes = runRPM("--querytags");
49          StringTokenizer strToken = new StringTokenizer(originTypes, "\r\n");
50  
51          int error = 0;
52          while (strToken.hasMoreTokens()) {
53              String tagName = strToken.nextToken();
54              EnumIf enum = RPMHeaderTag.getEnumByName(tagName);
55              assertNotNull("TAG <" + tagName + "> not found", enum);
56              if (enum.equals(RPMHeaderTag.UNKNOWN)) {
57                  logger.error("TAG <" + tagName + "> not found");
58                  error++;
59              }
60              //assertFalse("TAG <" + tagName + "> not found", enum
61              //        .equals(RPMHeaderTag.UNKNOWN));
62          }
63          assertFalse(error + " Errors", error > 0);
64      }
65  
66      /***
67       * Tests the jRPM for correct returned tags. The tags will be querried from
68       * a installed instance of rpm with the options --querytags. Than the
69       * results of rpm and jRPM are compared for each tag. If one tag differs
70       * the test will fail.
71       * 
72       * @throws IOException
73       *            if some io error occurs @warn For this test to work you need
74       *            rpm installed on your system.
75       */
76      public void testTestRPMFile() throws IOException {
77          String originTypes = runRPM("--querytags");
78          StringTokenizer strToken = new StringTokenizer(originTypes, "\r\n");
79          RPMFile rpmFile = new RPMFile(getTestRPMFile(RPM_FILE));
80          rpmFile.parse();
81          String rpmPath = getTestRPMFile(RPM_FILE).toString();
82          assertNotNull(rpmPath);
83          assertFalse(rpmPath.equals(""));
84  
85          // do some windows specific stuff
86          if (System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) {
87              rpmPath = rpmPath.replace('//', '/');
88          }
89  
90          if (logger.isDebugEnabled()) {
91              logger.debug("Starting compare for " + RPM_FILE + " ...");
92          }
93  
94          int errors = 0;
95          int ok = 0;
96  
97          while (strToken.hasMoreTokens()) {
98              String tagName = strToken.nextToken();
99              DataTypeIf rpmData = rpmFile.getTag(tagName);
100             long tagId = rpmFile.getTagIdForName(tagName);
101             String jrpmTagValue = (rpmData != null) ? rpmData.toString() : "";
102             StringTokenizer jrpmToken = new StringTokenizer(jrpmTagValue, "[],");
103 
104             String origTagValue = "";
105 
106             //if (jrpmToken.countTokens() == 1) {
107             if (rpmData == null || !rpmData.isArray()) {
108                 origTagValue = runRPM("-qp --queryformat \"%{" + tagName
109                         + "}\" " + rpmPath);
110             } else {
111                 origTagValue = runRPM("-qp --queryformat \"//[[%{" + tagName
112                         + "}, ]//]\" " + rpmPath);
113             }
114 
115             while (origTagValue.indexOf("(none)") >= 0) {
116                 origTagValue = origTagValue.replaceAll("//(none//)", "");
117             }
118 
119             while (origTagValue.indexOf("(unknown type)") >= 0) {
120                 origTagValue = origTagValue
121                         .replaceAll("//(unknown type//)", "");
122             }
123 
124             if (origTagValue.endsWith("\r\n")) {
125                 origTagValue = origTagValue.substring(0,
126                         origTagValue.length() - 2);
127             }
128 
129             StringTokenizer origToken = new StringTokenizer(origTagValue, "[],");
130             int origTokenCount = origToken.countTokens();
131 
132             if (rpmData != null && rpmData.isArray()) {
133                 origTokenCount--;
134             }
135 
136             if (jrpmToken.countTokens() != origTokenCount) {
137                 logger.error(tagName + ":" + tagId + " not ok! "
138                         + jrpmToken.countTokens() + ":" + origTokenCount + " <"
139                         + jrpmTagValue + "> <" + origTagValue + ">");
140                 errors++;
141             } else {
142                 logger.debug(tagName + ":" + tagId + " ok! <" + origTagValue
143                         + ">");
144                 ok++;
145             }
146 
147             //assertEquals(jrpmTagValue, origTagValue.replaceAll("\r\n",""));
148         }
149 
150         assertFalse(errors + " Errors found;see log error output (" + ok
151                 + " values ok)", errors > 0);
152     }
153 
154     protected void setUp() throws Exception {
155         if (!Logger.getLogger("com.jguild.jrpm").getAllAppenders()
156                 .hasMoreElements()) {
157             Logger.getLogger("com.jguild.jrpm").addAppender(
158                     new ConsoleAppender(new SimpleLayout()));
159         }
160 
161         // test if rpm is installed on this system
162         String version = runRPM("--version");
163         int index = version.indexOf("4.");
164         assertFalse("RPM version > 4 is needed!", index < 0);
165 
166         super.setUp();
167     }
168 
169     protected void tearDown() throws Exception {
170         super.tearDown();
171     }
172 
173     private File getTestRPMFile(String name) {
174         URL rpmUrl = NativeRPMTest.class.getClassLoader().getResource(name);
175         return new File(rpmUrl.getFile());
176     }
177 
178     /***
179      * Run an installed instance of rpm with the defined parameters.
180      * 
181      * @param command
182      *           Options to run rpm with
183      * @return stdout as a string
184      * @throws IOException
185      *            if an io error occurs during accessing rpm
186      */
187     private static String runRPM(String command) throws IOException {
188         Process rpmProc = Runtime.getRuntime().exec("rpm " + command);
189 
190         OutputStream err = new ByteArrayOutputStream();
191         OutputStream out = new ByteArrayOutputStream();
192 
193         // any error message?
194         StreamGobbler errorGobbler = new StreamGobbler(
195                 rpmProc.getErrorStream(), err);
196 
197         // any output?
198         StreamGobbler outputGobbler = new StreamGobbler(rpmProc
199                 .getInputStream(), out);
200 
201         // kick them off
202         errorGobbler.start();
203         outputGobbler.start();
204 
205         try {
206             // wait for process to stop
207             rpmProc.waitFor();
208         } catch (InterruptedException e) {
209             // process has ended, so do nothing
210         }
211 
212         return out.toString();
213     }
214 }