AbstractTestVersionControl.java
001 /*
002  *  AbstractTestVersionControl.java
003  *  Copyright (c) 1998-2008, The University of Sheffield.
004  *
005  *  This code is from the GATE project (http://gate.ac.uk/) and is free
006  *  software licenced under the GNU General Public License version 3. It is
007  *  distributed without any warranty. For more details see COPYING.txt in the
008  *  top level directory (or at http://gatewiki.sf.net/COPYING.txt).
009  *  
010  *  Hamish Cunningham 8/Sep/2005
011  */
012 
013 package gate.versioning.cmdline;
014 
015 import java.net.*;
016 import java.io.*;
017 import junit.framework.*;
018 import gate.util.*;
019 
020 /**
021  * Tests for version control API.
022  */
023 abstract public class AbstractTestVersionControl extends TestCase {
024 
025   protected String testsDirName = "/gate/versioncontrol/tests";
026   protected URL testDirURL = this.getClass().getResource(testsDirName);
027   protected String checkedOutDirName = "test";
028   protected String testFileName = "test.yam";
029   protected String testDirPath;
030   protected File rootDir;
031   protected File workingDir;
032   protected File checkedOutDir;
033   protected File newRootDir;
034   protected boolean DEBUG = false;
035   protected Repository rep;
036 
037   /** What type of repository implementation to use. */
038   abstract protected String getRepType();
039 
040   /** Basename of the repository directory. */
041   abstract protected String getRootName();
042 
043   /** Prefix of the repository directory (e.g. "file:///") or "". */
044   abstract protected String getRootPrefix();
045 
046   public AbstractTestVersionControl(String name) { super(name)}
047   
048   /** Create new repository object for testing */
049   public void setUp() throws
050     IOException, UnsupportedEncodingException, GateException,
051     ClassNotFoundException, InstantiationException, IllegalAccessException
052   {
053     // repository root and working dir
054     assertNotNull("Couldn't find resource " + testsDirName, testDirURL);
055     testDirPath = URLDecoder.decode(testDirURL.getPath()"UTF-8");
056     rootDir = new File(testDirPath + File.separator + getRootName());
057     workingDir = new File(testDirPath + File.separator + "checkout");
058     checkedOutDir = new File(testDirPath + "/checkout/" + checkedOutDirName);
059     newRootDir =
060       new File(testDirPath + File.separator + "new-" + getRootName());
061     
062     if(DEBUG) {
063       Out.prln("testDirURL: " + testDirURL);
064       Out.prln("testDirPath: " + testDirPath);
065       Out.prln("workingDir: " + workingDir);
066       Out.prln("rootDir: " + rootDir);
067       Out.prln("checkedOutDir: " + checkedOutDir);
068       Out.prln("newRootDir: " + newRootDir);
069     }
070 
071     // create a repository
072     rep = (RepositoryClass.forName(getRepType()).newInstance();
073     rep.setRoot(getRootPrefix() + rootDir.getCanonicalPath());
074     rep.setWorkingDir(workingDir);
075     rep.init();
076   // setUp
077 
078   /** Test initialisation */
079   public void testInit() {
080     rep.setWorkingDir(new File("/a/directory/which/does not/exist"));
081     try {
082       rep.init();
083     catch(GateException e) {
084       return;
085     }
086     fail("rep.init() failed to throw exception on non-existent dir");
087   // testInit()
088 
089   public void testCheckout() {
090     // checkout the test directory
091     boolean checkoutResult = rep.checkout(checkedOutDirName);
092     if(DEBUGOut.prln(rep.getCommandOutput());
093     assertTrue(
094       "test dir not checked out from rep : " + rep.getCommandOutput(),
095       checkoutResult
096     );
097     assertTrue(checkedOutDir.exists() && checkedOutDir.isDirectory());
098     File checkedOutFile = new File(checkedOutDir, testFileName);
099     assertTrue(checkedOutFile.exists() && ! checkedOutFile.isDirectory());
100 
101     // try to checkout a nonexistent directory
102     assertFalse("nonexistent dir co'd from rep", rep.checkout("zxczxc"));
103     File notCheckedOutDir = new File(testDirPath + "/checkout/zxczxc");
104     assertFalse(notCheckedOutDir.exists());
105   // testCheckout()
106 
107   public void testDiffAndCheckin() throws Exception {
108     assertFalse(
109       "starting testDiff but checkedOutDir exists: " + checkedOutDir.getPath(),
110       checkedOutDir.exists()
111     );
112 
113     // checkout the test directory
114     boolean checkoutResult = rep.checkout(checkedOutDirName);
115     assertTrue(
116       "test dir not checked out: " + rep.getCommandOutput(),
117       checkoutResult
118     );
119     assertTrue(checkedOutDir.exists() && checkedOutDir.isDirectory());
120 
121     // append a line to the test file
122 //    File checkedOutFile = new File(checkedOutDir, testFileName);
123 //    FileOutputStream fileOutStr = new FileOutputStream(checkedOutFile, true);
124 //    PrintWriter filePrinter = new PrintWriter(fileOutStr, true);
125 //    filePrinter.println("a new line");
126 //    filePrinter.flush();
127 //    filePrinter.close();
128 //    fileOutStr.flush();
129 //    fileOutStr.close();
130 //    checkedOutFile = null;
131 //    fileOutStr = null;
132 //    filePrinter = null;
133 //    Thread.currentThread().sleep(2000);\
134     File checkedOutFile = appendToTestFile();    
135     if(DEBUG) {
136       Out.prln(checkedOutFile.getPath());
137       Out.prln(Files.getString(checkedOutFile));
138     }
139 
140     // check that the new line is in the diffs from the repository version
141     // note that cvs may barf on \ in paths here :-(, so the following breaks:
142     // String diff = rep.diff(checkedOutFile.getPath());
143     String diff = rep.diff(checkedOutDirName + "/" + testFileName);
144     assertNotNull("null diff: " + rep.getCommandOutput(), diff);
145     assertTrue(
146       "incorrect difference (no new line): " + diff,
147       // hacky way to cater for both CVS and SVN diff styles
148       diff.indexOf("> a new line"!= -|| diff.indexOf("+a new line"!= -1
149     );
150 
151     // check in the file
152     boolean checkinResult =
153       rep.checkin(checkedOutDirName + "/" + testFileName);
154     assertTrue("checkin failed: " + rep.getCommandOutput(), checkinResult);
155 
156     // check that there's now no difference
157     diff = rep.diff(checkedOutDirName + "/" + testFileName);
158     assertNotNull("null diff: " + rep.getCommandOutput(), diff);
159     assertTrue(
160       "incorrect difference (should be none): " + diff, diff.equals("")
161     );
162   // testDiffAndCheckin()
163 
164   public void testUpdate() {
165     // checkout the test directory
166     boolean checkoutResult = rep.checkout(checkedOutDirName);
167 
168     // delete the test file and check it doesn't exist
169     File checkedOutFile = new File(checkedOutDir, testFileName);
170     checkedOutFile.delete();
171     assertFalse(checkedOutFile.exists());
172 
173     // update the test file and check it exists
174     boolean updateResult = rep.update(checkedOutDirName + "/" + testFileName);
175     assertTrue(
176       "test file not updated: " + rep.getCommandOutput(), updateResult
177     );
178     checkedOutFile = new File(checkedOutDir, testFileName);
179     assertTrue(
180       "test file doesn't exist or is not a file: " + rep.getCommandOutput(),
181       checkedOutFile.exists() && ! checkedOutFile.isDirectory()
182     );
183   // testUpdate()
184 
185   public void testStatus() {
186     // checkout the test directory
187     boolean checkoutResult = rep.checkout(checkedOutDirName);
188 
189     // get status of test file
190     File checkedOutFile = new File(checkedOutDir, testFileName);
191     String status = rep.status(checkedOutDirName + "/" + testFileName);
192   // testStatus()
193 
194   public void testAddAndDelete() {
195     // checkout the test dir
196     boolean result = rep.checkout(checkedOutDirName);
197 
198     // move the test file to a new name and delete it
199     File checkedOutFile = new File(checkedOutDir, testFileName);
200     File newTestFile = new File(checkedOutDir, "new-test.yam");
201     checkedOutFile.renameTo(newTestFile);
202     assertFalse(
203       "moved file exists: " + checkedOutFile, checkedOutFile.exists()
204     );
205     result = rep.delete(checkedOutDirName + "/" + testFileName);
206     assertTrue("couldn't delete file: " + rep.getCommandOutput(), result);
207     result = rep.checkin(checkedOutDirName + "/" + testFileName);
208     assertTrue(
209       "couldn't check in deleted file: " + rep.getCommandOutput(), result
210     );
211 
212     // add the test file under the new name
213     result = rep.add(checkedOutDirName + "/" "new-test.yam");
214     assertTrue("couldn't add new file: " + rep.getCommandOutput(), result);
215     result = rep.checkin(checkedOutDirName + "/" "new-test.yam");
216     assertTrue(
217       "couldn't check in added file: " + rep.getCommandOutput(), result
218     );
219 
220     // move it back for other tests to use
221     checkedOutFile = new File(checkedOutDir, testFileName);
222     newTestFile = new File(checkedOutDir, "new-test.yam");
223     newTestFile.renameTo(checkedOutFile);
224     assertFalse("moved file exists: " + newTestFile, newTestFile.exists());
225     result = rep.delete(checkedOutDirName + "/" "new-test.yam");
226     assertTrue("couldn't delete file: " + rep.getCommandOutput(), result);
227     result = rep.checkin(checkedOutDirName + "/" "new-test.yam");
228     assertTrue(
229       "couldn't check in deleted file: " + rep.getCommandOutput(), result
230     );
231     result = rep.add(checkedOutDirName + "/" + testFileName);
232     assertTrue("couldn't add new file: " + rep.getCommandOutput(), result);
233     result = rep.checkin(checkedOutDirName + "/" + testFileName);
234     assertTrue(
235       "couldn't check in added file: " + rep.getCommandOutput(), result
236     );
237   // testAddAndDelete()
238 
239   public void testCreate() throws GateException {
240     newRootDir =
241       new File(testDirPath + File.separator + "new-" + getRootName());
242     boolean result = rep.create(newRootDir.getPath());
243     assertTrue(
244       "new repository not created: " + rep.getCommandOutput(), result
245     );
246     assertTrue(newRootDir.exists() && newRootDir.isDirectory());
247   // testCreate()
248   
249   /**
250    
251    @throws Exception
252    */
253   public void testStatusIndicators() throws Exception {
254     checkOutTestDir();
255     String checkedOutFileName = checkedOutDirName + "/" + testFileName;
256     assertFalse("test file is modified", rep.isModified(checkedOutFileName));
257     assertFalse("test file out of date", rep.isOutOfDate(checkedOutFileName));
258     assertFalse("test file is unknown", rep.isUnknown(checkedOutFileName));
259 
260     File testFile = appendToTestFile();
261     assertTrue("test file not modified", rep.isModified(checkedOutFileName));
262     assertTrue(
263       "non-existent file not unknown",
264       rep.isUnknown("non-existent-------")
265     );
266     assertFalse(
267       "non-existent file modified",
268       rep.isModified("non-existent-------")
269     );
270     assertFalse(
271       "non-existent file out of date",
272       rep.isOutOfDate("non-existent-------")
273     );
274   // testStatusIndicators
275 
276   /**
277    * Test the operation of {@link Repository#importDir(String)}.
278    @throws GateException
279    */
280   public void testImport() throws Exception {
281     String name = "import-test-" + rep.getCommandName();
282     File homeDir = new File(testDirPath + File.separator + name);
283     if(homeDir.exists()) Files.rmdir(homeDir);
284     
285     homeDir = null;
286 //    Thread.currentThread().sleep(2000);
287     homeDir = new File(testDirPath + File.separator + name);
288     if(homeDir.exists()) Files.rmdir(homeDir);
289     
290     assertFalse(homeDir.getPath() " still exists", homeDir.exists());
291     homeDir = new File(testDirPath + File.separator + name);
292     if(! homeDir.mkdirs())
293       throw new GateException("couldn't create directory " + homeDir.getPath());
294     assertTrue(
295       homeDir.getPath() " isn't a dir"
296       homeDir.exists() && homeDir.isDirectory()
297     );
298     boolean status = rep.importDir(homeDir.getPath());
299     if(!statusthrow new 
300       GateException("import failed: " + rep.getCommandOutput());
301       
302     Files.rmdir(homeDir);
303     homeDir = null;
304 //    Thread.currentThread().sleep(2000);
305     homeDir = new File(testDirPath + File.separator + name);
306     if(homeDir.exists()) Files.rmdir(homeDir);
307     assertFalse("homeDir still exists", homeDir.exists());
308     
309     homeDir = null;
310 //    Thread.currentThread().sleep(2000);
311     homeDir = new File(testDirPath + File.separator + name);
312     if(homeDir.exists()) Files.rmdir(homeDir);
313     assertFalse("homeDir still exists", homeDir.exists());
314     
315     status = rep.checkout(name);
316     if(!statusthrow new 
317       GateException("couldn't checkout: " + rep.getCommandOutput());
318   // testImport()
319 
320   /**
321    * Check that testImport can run twice on the same test fixture 
322    * without failing.
323    @throws GateException
324    */
325   public void testImport2() throws Exception {
326     testImport();
327   }
328 
329   /**
330    * Check testExists.
331    */
332   public void testExists() throws Exception {
333     checkOutTestDir();
334     assertTrue(
335       "test dir is unknown: " + rep.getCommandOutput()
336       rep.exists(checkedOutDirName)
337     );
338     assertFalse("unknown dir exists", rep.exists("thing-thing-thing"));
339   }
340   
341   /**
342    * Lifecycle test - import, existence, checkout, modify, ...
343    */
344   public void testLifeCycle() throws Exception {
345     // create a new empty directory containing a checkout directory
346     File testDir;
347     testDir = new File("build/test-life-cycle");
348     if(testDir.exists()) Files.rmdir(testDir);
349     testDir = new File("build/test-life-cycle");
350     assertFalse("testDir still exists", testDir.exists());
351     testDir = new File("build/test-life-cycle/checkout");
352     if(! testDir.mkdirs())
353       fail("couldn't create testDir");
354     assertTrue(testDir.exists());
355     
356     // create a file in the checkout directory
357     File testFile;
358     testFile = new File(testDir, "test-file.txt");
359     FileOutputStream testFileOS = new FileOutputStream(testFile);
360     PrintWriter testFileBS = new PrintWriter(testFileOS);
361     testFileBS.println("test file line 1");
362     testFileBS.flush();
363     testFileBS.close();
364     testFileOS.flush();
365     testFileOS.close();
366     testFile = null;
367     
368     // create a repository root
369     Repository creatorRep = 
370       (RepositoryClass.forName(getRepType()).newInstance();
371     File rootFile = new File(testDir.getParentFile()"reproot");
372     creatorRep.create(rootFile.getAbsolutePath());
373     assertTrue("new root doesn't exist", rootFile.exists());
374     rootFile = null;
375     creatorRep = null;
376     
377     // create a repository object
378     Repository rep = (RepositoryClass.forName(getRepType()).newInstance();
379     rootFile = new File(testDir.getParentFile()"reproot");
380     rep.setRoot(rootFile.getAbsolutePath());
381     rep.setWorkingDir(testDir);
382     rep.init();
383     
384     // check we don't know about non-existent modules
385     assertTrue("non-existent module known by rep", rep.isUnknown("zxczxc"));
386     
387     // import the something, check it out....
388     
389   // testLifeCycle()
390   
391   /** Delete any checked-out files */
392   public void tearDown() {
393     Files.rmdir(checkedOutDir);
394     assertFalse(
395       "checkedOutDir exists: " + checkedOutDir.getPath(),
396       checkedOutDir.exists()
397     );
398     if(DEBUGOut.prln("tearDown has deleted " + checkedOutDir.getPath());
399     Files.rmdir(newRootDir);
400     assertFalse(
401       "newRootDir exists: " + newRootDir.getPath(),
402       newRootDir.exists()
403     );
404   // tearDown()
405   
406   /**
407    * Helper function for external users of this class. Check out test dir.
408    @return Repository the repository.
409    */
410   public Repository checkOutTestDir() throws Exception {
411     boolean checkoutResult = rep.checkout(checkedOutDirName);
412     assertTrue(
413       "test dir not checked out: " + rep.getCommandOutput(),
414       checkoutResult
415     );
416     assertTrue(checkedOutDir.exists() && checkedOutDir.isDirectory());
417 
418     return rep;
419   // checkOutTestDir
420 
421   /**
422    * Helper function for external users of this class. Append line to test
423    * file. 
424    @return File the checked out file.
425    */
426   public File appendToTestFile() throws Exception {
427     File checkedOutFile = new File(checkedOutDir, testFileName);
428     long fileSize = checkedOutFile.length();
429     FileOutputStream fileOutStr = new FileOutputStream(checkedOutFile, true);
430     PrintWriter filePrinter = new PrintWriter(fileOutStr, true);
431     filePrinter.println("a new line");
432     filePrinter.flush();
433     filePrinter.close();
434     fileOutStr.flush();
435     fileOutStr.close();
436     if(DEBUG) {
437       Out.prln(checkedOutFile.getPath());
438       Out.prln(Files.getString(checkedOutFile));
439     }
440     assertTrue("File not modified after addition"
441             checkedOutFile.length() > fileSize);
442     return checkedOutFile;
443   // appendToTestFile
444 
445 
446 // AbstractTestVersionControl