View Javadoc
1   package org.melati.poem.test;
2   
3   import java.io.FileNotFoundException;
4   import java.io.IOException;
5   import java.io.InputStream;
6   import java.util.Enumeration;
7   import java.util.Properties;
8   
9   import org.melati.poem.AccessToken;
10  import org.melati.poem.Database;
11  import org.melati.poem.DatabaseInitialisationPoemException;
12  import org.melati.poem.Group;
13  import org.melati.poem.Persistent;
14  import org.melati.poem.PoemDatabase;
15  import org.melati.poem.PoemDatabaseFactory;
16  import org.melati.poem.PoemTask;
17  import org.melati.poem.Table;
18  import org.melati.poem.User;
19  import org.melati.poem.transaction.WriteCommittedException;
20  import org.melati.poem.util.EnumUtils;
21  
22  import junit.framework.Test;
23  import junit.framework.TestCase;
24  
25  /**
26   * FIXME Postgresql seems to think that the committed transaction is in a funny state. 
27   * 
28   * @author timp
29   * @since 19-January-2007
30   */
31  public class DatabasePerformInCommittedTransactionTest 
32     extends TestCase implements Test {
33  
34    /**
35     * The name of the test case
36     */
37  
38    private PoemDatabase db = null;
39  
40    private String dbName = "melatijunit";
41    
42    private AccessToken userToRunAs;
43    
44    boolean skipTest = false;
45  
46    /**
47     * Constructor.
48     */
49    public DatabasePerformInCommittedTransactionTest() {
50      super();
51    }
52  
53    /**
54     * Constructor.
55     * 
56     * @param name
57     */
58    public DatabasePerformInCommittedTransactionTest(String name) {
59      super(name);
60    }
61  
62    String dbUrl = null;
63    /**
64     * @see TestCase#setUp()
65     */
66    protected void setUp() throws Exception {
67      super.setUp();
68      setDbName(getDbName());
69      setDb(getDbName());
70    }
71  
72    /**
73     * @see TestCase#tearDown()
74     */
75    protected void tearDown() throws Exception {
76      checkDbUnchanged();
77    }
78  
79    protected void checkDbUnchanged() {
80      getDb().inSession(AccessToken.root,
81              new PoemTask() {
82                public void run() {
83                  if (dbName.equals("poemtest")) {
84                    poemtestUnchanged();
85                  } 
86                  if (dbName.equals("melatijunit")) {
87                    melatijunitUnchanged();
88                  }
89                }
90              });
91  
92    }
93    protected void melatijunitUnchanged() { 
94      if (!getDb().getDbms().canDropColumns()) {
95        return;
96      }
97      assertEquals(0, getDb().getSettingTable().count());
98      assertEquals(1, getDb().getGroupTable().count());
99      assertEquals(1, getDb().getGroupMembershipTable().count());
100     assertEquals(5, getDb().getCapabilityTable().count());
101     assertEquals(1, getDb().getGroupCapabilityTable().count());
102     assertEquals(3, getDb().getTableCategoryTable().count());
103     assertEquals(2, getDb().getUserTable().count());
104     assertEquals(69, getDb().getColumnInfoTable().count());
105     assertEquals(9, getDb().getTableInfoTable().count());
106   }
107   protected void poemtestUnchanged() { 
108     assertEquals(0, getDb().getSettingTable().count());
109     assertEquals(1, getDb().getGroupTable().count());
110     assertEquals(1, getDb().getGroupMembershipTable().count());
111     assertEquals(5, getDb().getCapabilityTable().count());
112     assertEquals(1, getDb().getGroupCapabilityTable().count());
113     assertEquals(4, getDb().getTableCategoryTable().count());
114     assertEquals(2, getDb().getUserTable().count());
115     //dumpTable(getDb().getColumnInfoTable());
116     // Until table.dropColumnAndCommit() arrives...
117     assertEquals(147, getDb().getColumnInfoTable().count());
118     assertEquals(23, getDb().getTableInfoTable().count());
119 
120   }
121   protected <P extends Persistent> void dumpTable(Table<P> t) {
122     Enumeration<P> them = t.selection();
123     while (them.hasMoreElements()) {
124       Persistent it = (Persistent)them.nextElement();
125       System.err.println(it.getTroid() + " " + it.getCooked("name") + " " +
126           it.getTable().getName());
127     }
128     
129   }
130   /**
131    * @return Returns the dbName.
132    */
133   protected String getDbName() {
134     return this.dbName;
135   }
136 
137   /**
138    * @param dbName
139    *          The dbName to set.
140    */
141   protected void setDbName(String dbName) {
142     this.dbName = dbName;
143   }
144 
145   /**
146    * @return Returns the db.
147    */
148   public PoemDatabase getDb() {
149     return db;
150   }
151 
152   /**
153    * @param dbName the name of the db to set
154    */
155   public void setDb(String dbName) {
156     if (dbName == null)
157       throw new NullPointerException();
158     try {
159       db = (PoemDatabase)getDatabase(dbName);
160     } catch (DatabaseInitialisationPoemException e) {
161       e.printStackTrace();
162       fail(e.getMessage());
163     }
164   }
165 
166   /**
167    * @param name the name of the logical database
168    * @return a database with that name 
169    */
170   public Database getDatabase(String name){ 
171     Properties defs = databaseDefs();
172     String pref = "org.melati.poem.test.PoemTestCase." + name + ".";
173     if (PoemTestCase.getOrDie(defs, pref + "dbmsclass").indexOf("Postgres") > 0) skipTest = true;
174 
175     return PoemDatabaseFactory.getDatabase(name,
176             PoemTestCase.getOrDie(defs, pref + "url"), 
177             PoemTestCase.getOrDie(defs, pref + "user"),
178             PoemTestCase.getOrDie(defs, pref + "password"),
179             PoemTestCase.getOrDie(defs, pref + "class"),
180             PoemTestCase.getOrDie(defs, pref + "dbmsclass"),
181             new Boolean(PoemTestCase.getOrDie(defs, pref + "addconstraints")).booleanValue(),
182             new Boolean(PoemTestCase.getOrDie(defs, pref + "logsql")).booleanValue(),
183             new Boolean(PoemTestCase.getOrDie(defs, pref + "logcommits")).booleanValue(),
184             new Integer(PoemTestCase.getOrDie(defs, pref + "maxtransactions")).intValue());
185   }
186 
187   /** Properties, named for this class. */
188   public static Properties databaseDefs = null;
189   /**
190    * @return the database defs
191    */
192   public  Properties databaseDefs() {
193     if (databaseDefs == null)
194       databaseDefs = getProperties();
195     return databaseDefs;
196   }
197   /**
198    * @return a properties object
199    */
200   public Properties getProperties() {
201     String className = "org.melati.poem.test.PoemTestCase";
202     String name = className + ".properties";
203     InputStream is = this.getClass().getResourceAsStream(name);
204 
205     if (is == null)
206       throw new RuntimeException(new FileNotFoundException(name + ": is it in CLASSPATH?"));
207 
208     Properties them = new Properties();
209     try {
210       them.load(is);
211     } catch (IOException e) {
212       throw new RuntimeException(new IOException("Corrupt properties file `" + name + "': " +
213       e.getMessage()));
214     }
215     return them;
216   }
217 
218   
219   /**
220    * @return the user
221    */
222   public AccessToken getUserToRunAs() {
223     if (userToRunAs == null) return AccessToken.root;
224     return userToRunAs;
225   }
226 
227   /**
228    * @param userToRunAs the user to set
229    */
230   public void setUserToRunAs(AccessToken userToRunAs) {
231     if (userToRunAs == null) 
232       this.userToRunAs = AccessToken.root;
233     else
234       this.userToRunAs = userToRunAs;
235   }
236 
237   /**
238    * @see org.melati.poem.Database#inCommittedTransaction(AccessToken, PoemTask)
239    */
240   public void testInCommittedTransaction() {
241     PoemTask doNothing = new PoemTask() {
242       public void run() {
243       }
244     };
245     getDb().inCommittedTransaction(AccessToken.root, doNothing);
246     
247   }
248 
249   /**
250    * @see org.melati.poem.Database#inCommittedTransaction(AccessToken, PoemTask)
251    */
252   public void testReadInCommittedTransaction() {
253     if (skipTest) return;
254     PoemTask read = new PoemTask() {
255       public void run() {
256         assertEquals("Melati guest user",
257                 ((User)getDb().getUserTable().getObject(new Integer(0))).getName());
258       }
259     };
260 
261     getDb().inCommittedTransaction(AccessToken.root, read);
262     getDb().uncache();
263     getDb().inCommittedTransaction(AccessToken.root, read);
264     
265   }
266   
267   /**
268    * @see org.melati.poem.Database#inCommittedTransaction(AccessToken, PoemTask)
269    */
270   public void testUpdateInCommittedTransaction() {
271     if (skipTest) return;
272     PoemTask modify = new PoemTask() {
273       public void run() {
274         try { 
275           getDb().guestUser().setName(getDb().guestUser().getName());
276           fail("Should have blown up");
277         } catch (WriteCommittedException e ) { 
278           e = null;
279         }
280       }
281     };
282     getDb().inCommittedTransaction(AccessToken.root, modify);
283     
284   }
285   
286   /**
287    * @see org.melati.poem.Database#inCommittedTransaction(AccessToken, PoemTask)
288    */
289   public void testDeleteInCommittedTransaction() {
290     if (skipTest) return;
291     PoemTask modify = new PoemTask() {
292       public void run() {
293         try { 
294           getDb().guestUser().delete_unsafe();
295           fail("Should have blown up");
296         } catch (WriteCommittedException e ) { 
297           e = null;
298         }
299       }
300     };
301     getDb().inCommittedTransaction(AccessToken.root, modify);
302     
303   }
304   
305   /**
306    * It might be a good idea to handle this more elegantly than by throwing NPE. 
307    * @see org.melati.poem.Database#inCommittedTransaction(AccessToken, PoemTask)
308    */
309   public void testCreateInCommittedTransaction() {
310     if (skipTest) return;
311     PoemTask create = new PoemTask() {
312       public void run() {
313         try { 
314           Group g = (Group)getDb().getGroupTable().newPersistent();
315           g.setName("failure");
316           g.makePersistent();
317           fail("Should have blown up");
318         } catch (NullPointerException e ) { 
319           e = null;
320         }
321       }
322     };
323     getDb().inCommittedTransaction(AccessToken.root, create);
324     create = new PoemTask() {
325       public void run() {
326         try { 
327           getDb().getGroupTable().ensure("failure");
328           fail("Should have blown up");
329         } catch (NullPointerException e ) { 
330           e = null;
331         }
332       }
333     };
334   }
335   
336   /**
337    * @see org.melati.poem.Database#toString()
338    */
339   public void testToString() {
340     PoemDatabase d = new PoemDatabase();
341     assertEquals("unconnected database", d.toString());
342   }
343   
344   /**
345    * Test troidSelection uses committed transaction.
346    */
347   public void testTableTroidSelection() {
348     getDb().inSession(AccessToken.root,
349             new PoemTask() {
350               public void run() {
351                 Enumeration<Integer> en = getDb().getUserTable().troidSelection("id=0",null, false);
352                 assertEquals(1, EnumUtils.vectorOf(en).size());
353               }
354             });
355   }
356   
357   /**
358    * Test that committed transaction is used.
359    */
360   public void testTableCount() {
361     if (skipTest) return;
362     getDb().setLogSQL(true);
363     assertEquals(1, getDb().getGroupTable().count());
364     getDb().setLogSQL(false);
365     assertEquals(1, getDb().getGroupTable().count(null, true));
366     
367   }
368 }