1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j;
19  
20  
21  import org.apache.log4j.Level;
22  import org.apache.log4j.Logger;
23  import java.util.Random;
24  
25  /*
26    Stress test the Logger class.
27  
28  */
29  
30  class StressCategory {
31  
32    static Level[] level = new Level[] {Level.DEBUG, 
33  				      Level.INFO, 
34  				      Level.WARN,
35  				      Level.ERROR,
36  				      Level.FATAL};
37  
38    static Level defaultLevel = Logger.getRootLogger().getLevel();
39    
40    static int LENGTH;
41    static String[] names;
42    static Logger[] cat;
43    static CT[] ct;
44  
45    static Random random = new Random(10);
46  
47    public static void main(String[] args) {
48      
49      LENGTH = args.length;
50  
51      if(LENGTH == 0) {
52        System.err.println( "Usage: java " + StressCategory.class.getName() +
53  			  " name1 ... nameN\n.");      
54        System.exit(1);
55      }
56      if(LENGTH >= 7) {
57        System.err.println(
58          "This stress test suffers from combinatorial explosion.\n"+
59          "Invoking with seven arguments takes about 90 minutes even on fast machines");
60      }
61  
62      names = new String[LENGTH];
63      for(int i=0; i < LENGTH; i++) {
64        names[i] = args[i];
65      }    
66      cat = new Logger[LENGTH];
67      ct = new CT[LENGTH]; 
68  
69  
70      permute(0); 
71  
72      // If did not exit, then passed all tests.
73    }
74  
75    // Loop through all permutations of names[].
76    // On each possible permutation call createLoop
77    static
78    void permute(int n) {
79      if(n == LENGTH)
80        createLoop(0);
81      else
82        for(int i = n; i < LENGTH; i++) {
83  	swap(names, n, i);
84  	permute(n+1);
85  	swap(names, n, i);	
86        }
87    }
88  
89    static
90    void swap(String[] names, int i, int j) {
91      String t = names[i];
92      names[i] = names[j];
93      names[j] = t;
94    }
95    
96    public
97    static
98    void permutationDump() {
99      System.out.print("Current permutation is - ");
100     for(int i = 0; i < LENGTH; i++) {
101       System.out.print(names[i] + " ");
102     }
103     System.out.println();
104   }
105 
106 
107   // Loop through all possible 3^n combinations of not instantiating, 
108   // instantiating and setting/not setting a level.
109 
110   static
111   void createLoop(int n) {
112     if(n == LENGTH) {  
113       //System.out.println("..............Creating cat[]...........");
114       for(int i = 0; i < LENGTH; i++) {
115 	if(ct[i] == null)
116 	  cat[i] = null;
117 	else {
118 	  cat[i] = Logger.getLogger(ct[i].catstr);
119 	  cat[i].setLevel(ct[i].level);
120 	}
121       }
122       test();
123       // Clear hash table for next round
124       Hierarchy h = (Hierarchy) LogManager.getLoggerRepository();
125       h.clear();
126     }
127     else {      
128       ct[n]  = null;
129       createLoop(n+1);  
130 
131       ct[n]  = new CT(names[n], null);
132       createLoop(n+1);  
133       
134       int r = random.nextInt(); if(r < 0) r = -r;
135       ct[n]  = new CT(names[n], level[r%5]);
136       createLoop(n+1);
137     }
138   }
139 
140 
141   static
142   void test() {    
143     //System.out.println("++++++++++++TEST called+++++++++++++");
144     //permutationDump();
145     //catDump();
146 
147     for(int i = 0; i < LENGTH; i++) {
148       if(!checkCorrectness(i)) {
149 	System.out.println("Failed stress test.");
150 	permutationDump();
151 	
152 	//Hierarchy._default.fullDump();
153 	ctDump();
154 	catDump();
155 	System.exit(1);
156       }
157     }
158   }
159   
160   static
161   void ctDump() {
162     for(int j = 0; j < LENGTH; j++) {
163        if(ct[j] != null) 
164 	    System.out.println("ct [" + j + "] = ("+ct[j].catstr+"," + 
165 			       ct[j].level + ")");
166        else 
167 	 System.out.println("ct [" + j + "] = undefined");
168     }
169   }
170   
171   static
172   void catDump() {
173     for(int j = 0; j < LENGTH; j++) {
174       if(cat[j] != null)
175 	System.out.println("cat[" + j + "] = (" + cat[j].name + "," +
176 			   cat[j].getLevel() + ")");
177       else
178 	System.out.println("cat[" + j + "] = undefined"); 
179     }
180   }
181 
182   //  static
183   //void provisionNodesDump() {
184   //for (Enumeration e = CategoryFactory.ht.keys(); e.hasMoreElements() ;) {
185   //  CategoryKey key = (CategoryKey) e.nextElement();
186   //  Object c = CategoryFactory.ht.get(key);
187   //  if(c instanceof  ProvisionNode) 
188   //((ProvisionNode) c).dump(key.name);
189   //}
190   //}
191   
192   static
193   boolean checkCorrectness(int i) {
194     CT localCT = ct[i];
195 
196     // Can't perform test if logger is not instantiated
197     if(localCT == null) 
198       return true;
199     
200     // find expected level
201     Level expected = getExpectedPrioriy(localCT);
202 
203 			    
204     Level purported = cat[i].getEffectiveLevel();
205 
206     if(expected != purported) {
207       System.out.println("Expected level for " + localCT.catstr + " is " +
208 		       expected);
209       System.out.println("Purported level for "+ cat[i].name + " is "+purported);
210       return false;
211     }
212     return true;
213       
214   }
215 
216   static
217   Level getExpectedPrioriy(CT ctParam) {
218     Level level = ctParam.level;
219     if(level != null) 
220       return level;
221 
222     
223     String catstr = ctParam.catstr;    
224     
225     for(int i = catstr.lastIndexOf('.', catstr.length()-1); i >= 0; 
226 	                              i = catstr.lastIndexOf('.', i-1))  {
227       String substr = catstr.substring(0, i);
228 
229       // find the level of ct corresponding to substr
230       for(int j = 0; j < LENGTH; j++) {	
231 	if(ct[j] != null && substr.equals(ct[j].catstr)) {
232 	  Level p = ct[j].level;
233 	  if(p != null) 
234 	    return p;	  
235 	}
236       }
237     }
238     return defaultLevel;
239   }
240 
241   
242 
243   static class CT {
244     public String   catstr;
245     public Level level;
246 
247     CT(String catstr,  Level level) {
248       this.catstr = catstr;
249       this.level = level;
250     }
251   }
252 }