package org.codehaus.plexus.components.io.attributes; /* * Copyright 2007 The Codehaus Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import junit.framework.Assert; import org.codehaus.plexus.components.io.attributes.AttributeParser.NumericUserIDAttributeParser; import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; import org.codehaus.plexus.util.cli.CommandLineUtils; import org.codehaus.plexus.util.cli.Commandline; import org.codehaus.plexus.util.cli.StreamConsumer; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Locale; import java.util.Map; import junit.framework.TestCase; import static org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributeUtils.getFileAttributes; public class PlexusIoResourceAttributeUtilsTest extends TestCase { private Locale origSystemLocale; @Override protected void setUp() throws Exception { this.origSystemLocale = Locale.getDefault(); // sample ls output files have US date format and we use SimpleDateFormt with system locale for ls date format parsing // otherwise test could fail on systems with non-US locales Locale.setDefault( Locale.US ); } @Override protected void tearDown() throws Exception { Locale.setDefault( origSystemLocale ); } public void testGetAttributesForThisTestClass() throws IOException { if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) { System.out.println( "WARNING: Unsupported OS, skipping test" ); return; } URL resource = Thread.currentThread().getContextClassLoader().getResource( getClass().getName().replace( '.', '/' ) + ".class" ); if ( resource == null ) { throw new IllegalStateException( "SOMETHING IS VERY WRONG. CANNOT FIND THIS TEST CLASS IN THE CLASSLOADER." ); } File f = new File( resource.getPath().replaceAll( "%20", " " ) ); Map attrs = PlexusIoResourceAttributeUtils.getFileAttributesByPath( f, true, true ); PlexusIoResourceAttributes fileAttrs = (PlexusIoResourceAttributes) attrs.get( f.getAbsolutePath() ); System.out.println( "Got attributes for: " + f.getAbsolutePath() + fileAttrs ); assertNotNull( fileAttrs ); assertTrue( fileAttrs.isOwnerReadable() ); assertEquals( System.getProperty( "user.name" ), fileAttrs.getUserName() ); } public void testFolderJava7() throws IOException, CommandLineException { if (Os.isFamily( Os.FAMILY_WINDOWS ) || Os.isFamily( Os.FAMILY_WIN9X )){ return; // Nothing to do here. } URL resource = Thread.currentThread().getContextClassLoader().getResource( getClass().getName().replace( '.', '/' ) + ".class" ); if ( resource == null ) { throw new IllegalStateException( "SOMETHING IS VERY WRONG. CANNOT FIND THIS TEST CLASS IN THE CLASSLOADER." ); } File f = new File( resource.getPath().replaceAll( "%20", " " ) ); final File aDir = f.getParentFile().getParentFile().getParentFile(); Commandline commandLine = new Commandline("chmod"); commandLine.addArguments(new String[]{"763", f.getAbsolutePath()}); CommandLineUtils.executeCommandLine(commandLine, null , null); Map attrs = PlexusIoResourceAttributeUtils.getFileAttributesByPath( aDir, true, true ); PlexusIoResourceAttributes fileAttrs = (PlexusIoResourceAttributes) attrs.get( f.getAbsolutePath() ); assertTrue( fileAttrs.isGroupReadable()); assertTrue( fileAttrs.isGroupWritable()); assertFalse( fileAttrs.isGroupExecutable()); assertTrue( fileAttrs.isOwnerExecutable()); assertTrue( fileAttrs.isOwnerReadable()); assertTrue( fileAttrs.isOwnerWritable()); assertTrue( fileAttrs.isWorldExecutable()); assertFalse( fileAttrs.isWorldReadable()); assertTrue( fileAttrs.isWorldWritable()); assertNotNull(fileAttrs); } public void testAttributeParsers() { assertTrue( PlexusIoResourceAttributeUtils.totalLinePattern.matcher( "totalt 420" ).matches() ); assertTrue( PlexusIoResourceAttributeUtils.totalLinePattern.matcher( "total 420" ).matches() ); assertTrue( PlexusIoResourceAttributeUtils.totalLinePattern.matcher( "JSHS 420" ).matches() ); } // to make a new testcase // Checkout plexus-io, and from the root of the module type the following: // ls -1nlaR src/main/java/org/codehaus/plexus/components >src/test/resources/`uname`-p1.txt // ls -1laR src/main/java/org/codehaus/plexus/components >src/test/resources/`uname`-p2.txt // Then a test-method that tests the output- public void ignoredTestParserUbuntu10_04_en() throws Exception { final Map map = checkStream( "Linux" ); final FileAttributes o = (FileAttributes) map.get( "src/main/java/org/codehaus/plexus/components/io/attributes/AttributeConstants.java" ); // -rw-r--r-- 1 1020 1030 11108 Mar 16 22:42 build.xml assertEquals( "-rw-rw-r--", new String( o.getLsModeParts() ) ); assertEquals( 1020, o.getUserId().intValue() ); assertEquals( 1030, o.getGroupId().intValue() ); // Should probably test pass 2 too... } public void testANotherOneWithTrouble() throws Exception { String output = "drwxr-xr-x+ 13 kristian staff 442 Oct 11 14:14 .."; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( output.getBytes() ); AttributeParser parser = getNameBasedParser1la(); parse( byteArrayInputStream, parser ); } public void testSingleLine() throws Exception { String output = "-rw-r--r-- 1 1003 1002 1533 2010-04-23 14:34 /home/bamboo/agent1/xml-data/build-dir/PARALLEL-CH1W/checkout/spi/pom.xml"; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( output.getBytes() ); AttributeParser parser = getNumericParser1nla(); parse( byteArrayInputStream, parser ); } public void testSrcResource() throws IOException { File dir = new File("src/test/resources/symlinks"); final Map<String, PlexusIoResourceAttributes> fileAttributesByPathScreenScrape = PlexusIoResourceAttributeUtils.getFileAttributesByPathScreenScrape( dir, true, true ); assertNotNull( fileAttributesByPathScreenScrape); PlexusIoResourceAttributes pr = null; for ( String s : fileAttributesByPathScreenScrape.keySet() ) { if (s.endsWith( "targetFile.txt" )) pr = fileAttributesByPathScreenScrape.get( s); } assertNotNull(pr); assertTrue(pr.getOctalMode() > 0); } public void testPermissionDenied() { File dir = new File("src/test/lsPerms"); try { PlexusIoResourceAttributeUtils.getFileAttributesByPathScreenScrape( dir, true, true ); // We could search for permission denied here and throw some kind of specialized exception. fail("We were supposed to get an io exceptions"); } catch (IOException ignore) { ignore.printStackTrace(); } } public void testReversedMonthDayOrder() throws Exception { String output = // "-rw-r--r-- 1 501 80 7683 31 May 10:06 pom_newer.xml\n" + // "-rwxr--r-- 1 502 81 7683 1 Jun 2010 pom_older.xml"; InputStream byteArrayInputStream = new ByteArrayInputStream( output.getBytes() ); NumericUserIDAttributeParser parser = getNumericParser1nla(); parse( byteArrayInputStream, parser ); Map<String, PlexusIoResourceAttributes> map = parser.getAttributesByPath(); // 6 months or newer ls date format FileAttributes newerFileAttr = (FileAttributes) map.get( "pom_newer.xml" ); assertNotNull( newerFileAttr ); assertEquals( "-rw-r--r--", new String( newerFileAttr.getLsModeParts() ) ); assertEquals( 501, newerFileAttr.getUserId().intValue() ); assertEquals( 80, newerFileAttr.getGroupId().intValue() ); // older than 6 months ls date format FileAttributes olderFileAttr = (FileAttributes) map.get( "pom_older.xml" ); assertNotNull( olderFileAttr ); assertEquals( "-rwxr--r--", new String( olderFileAttr.getLsModeParts() ) ); assertEquals( 502, olderFileAttr.getUserId().intValue() ); assertEquals( 81, olderFileAttr.getGroupId().intValue() ); } public void testOddLinuxFormatWithExtermelyLargeNumericsSingleLine() throws Exception { String output = "-rw-rw-r-- 1 4294967294 4294967294 7901 2011-06-07 18:39 /mnt/work/src/maven-plugins-trunk/maven-compiler-plugin/pom.xml"; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( output.getBytes() ); AttributeParser parser = getNumericParser1nla(); parse( byteArrayInputStream, parser ); } public void testMacOsWithSpace() throws Exception { String output = "-rwxrw--wx 1 kristian DOMZZZ\\Domain Users 15387 Oct 20 15:30 /Users/kristian/lsrc/plexus/plexus-io/target/test-classes/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtilsTest.class"; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( output.getBytes() ); AttributeParser parser = getNameBasedParser1la(); parse( byteArrayInputStream, parser ); final Map<String, PlexusIoResourceAttributes> attributesByPath = parser.getAttributesByPath(); String path = "/Users/kristian/lsrc/plexus/plexus-io/target/test-classes/org/codehaus/plexus/components/io/attributes/"; } public void testMacOsLine() throws Exception { String line = "drwxr-xr-x+ 3 1000 20 102 Oct 11 14:24 .."; ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( line.getBytes() ); AttributeParser parser = getNumericParser1nla(); parse( byteArrayInputStream, parser ); } public void ignoredTestParserCygwin() throws Exception { final Map map = checkStream( "CYGWIN_NT-5.1" ); final FileAttributes o = (FileAttributes) map.get( "src/main/java/org/codehaus/plexus/components/io/attributes/AttributeConstants.java" ); // -rw-r--r-- 1 1020 1030 11108 Mar 16 22:42 build.xml assertEquals( "-rw-r--r--", new String( o.getLsModeParts() ) ); assertEquals( 203222, o.getUserId().intValue() ); assertEquals( 10513, o.getGroupId().intValue() ); } public void testParserSolaris() throws Exception { checkStream( "SunOS" ); } public void testMisc() throws Exception { checkStream( "Test" ); } public void testParserFreeBsd() throws Exception { checkStream( "FreeBSD" ); } public void testParserb26() throws Exception { final Map<String, PlexusIoResourceAttributes> map = checkStream2( "b26-linux" ); PlexusIoResourceAttributes attrs = null; for ( String s : map.keySet() ) { if (s.endsWith( "App.java" )) attrs = map.get(s); } Assert.assertEquals( 0664, attrs.getOctalMode() ); } public void testMergeAttributesWithNullBase() { PlexusIoResourceAttributes override = new SimpleResourceAttributes( 1001, "myUser", 1001, "test", 0 ); PlexusIoResourceAttributes defaults = new SimpleResourceAttributes( 1000, "defaultUser", 1000, "defaultTest", 0 ); PlexusIoResourceAttributes attributes; attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, null, defaults ); assertEquals( Integer.valueOf( 1001 ), attributes.getGroupId() ); assertEquals( Integer.valueOf( 1001 ), attributes.getUserId() ); } public void testMergeAttributesWithNullOverrideGroup() { final PlexusIoResourceAttributes override = new SimpleResourceAttributes( 1001, "myUser", -1, null, 0 ); final PlexusIoResourceAttributes defaults = new SimpleResourceAttributes( 1000, "defaultUser", 1000, "defaultGroup", 0 ); PlexusIoResourceAttributes attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, null, defaults ); assertEquals( attributes.getGroupId(), Integer.valueOf( 1000 ) ); assertEquals( attributes.getUserId(), Integer.valueOf( 1001 ) ); } public void testMergeAttributesOverride() { final PlexusIoResourceAttributes blank = new SimpleResourceAttributes(); final PlexusIoResourceAttributes invalid = new SimpleResourceAttributes( -1, null, -1, null, -1 ); final PlexusIoResourceAttributes override = new SimpleResourceAttributes( 1111, "testUser", 2222, "testGroup", 0777 ); final PlexusIoResourceAttributes defaults = new SimpleResourceAttributes( 3333, "defaultUser", 4444, "defaultGroup", 0444 ); final PlexusIoResourceAttributes base = new SimpleResourceAttributes( 5555, "baseUser", 6666, "baseGroup", 0111 ); PlexusIoResourceAttributes attributes; // When override is null, base is returned verbatim attributes = PlexusIoResourceAttributeUtils.mergeAttributes( null, null, null ); assertNull( attributes ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( null, null, defaults ); assertNull( attributes ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( null, base, null ); assertSame( base, attributes ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( null, base, defaults ); assertSame( base, attributes ); // Test cases when override is non-null attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, null, null ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, base, null ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, null, defaults ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, base, defaults ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, blank, null ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( override, invalid, null ); assertEquals( Integer.valueOf( 1111 ), attributes.getUserId() ); assertEquals( "testUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 2222 ), attributes.getGroupId() ); assertEquals( "testGroup", attributes.getGroupName() ); assertEquals( 0777, attributes.getOctalMode() ); // Test cases when override has only blank values attributes = PlexusIoResourceAttributeUtils.mergeAttributes( blank, base, null ); assertEquals( Integer.valueOf( 5555 ), attributes.getUserId() ); assertEquals( "baseUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 6666 ), attributes.getGroupId() ); assertEquals( "baseGroup", attributes.getGroupName() ); assertEquals( 0111, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( invalid, base, null ); assertEquals( Integer.valueOf( 5555 ), attributes.getUserId() ); assertEquals( "baseUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 6666 ), attributes.getGroupId() ); assertEquals( "baseGroup", attributes.getGroupName() ); assertEquals( 0111, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( blank, base, defaults ); assertEquals( Integer.valueOf( 5555 ), attributes.getUserId() ); assertEquals( "baseUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 6666 ), attributes.getGroupId() ); assertEquals( "baseGroup", attributes.getGroupName() ); assertEquals( 0111, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( invalid, base, defaults ); assertEquals( Integer.valueOf( 5555 ), attributes.getUserId() ); assertEquals( "baseUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 6666 ), attributes.getGroupId() ); assertEquals( "baseGroup", attributes.getGroupName() ); assertEquals( 0111, attributes.getOctalMode() ); } public void testFileAttributes() throws IOException { PlexusIoResourceAttributes attrs = getFileAttributes( new File( "src/test/resources/symlinks/src/fileW.txt" ) ); assertFalse( attrs.isSymbolicLink() ); assertTrue( StringUtils.isNotEmpty( attrs.getUserName())); if (! Os.isFamily(Os.FAMILY_WINDOWS)) { assertTrue( StringUtils.isNotEmpty( attrs.getGroupName())); assertNotNull( attrs.getGroupId() ); assertNotNull( attrs.getUserId() ); } } public void testMergeAttributesDefault() { final PlexusIoResourceAttributes blank = new SimpleResourceAttributes(null, null, null, null, 0); final PlexusIoResourceAttributes invalid = new SimpleResourceAttributes( -1, null, -1, null, -1 ); final PlexusIoResourceAttributes defaults = new SimpleResourceAttributes( 3333, "defaultUser", 4444, "defaultGroup", 0444 ); PlexusIoResourceAttributes attributes; // Test cases when override and base have blank values attributes = PlexusIoResourceAttributeUtils.mergeAttributes( blank, blank, defaults ); assertEquals( Integer.valueOf( 3333 ), attributes.getUserId() ); assertEquals( "defaultUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 4444 ), attributes.getGroupId() ); assertEquals( "defaultGroup", attributes.getGroupName() ); // 0 is a borderline case, for backwards compatibility it is not overridden by value from defaults assertEquals( 0, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( invalid, blank, defaults ); assertEquals( Integer.valueOf( 3333 ), attributes.getUserId() ); assertEquals( "defaultUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 4444 ), attributes.getGroupId() ); assertEquals( "defaultGroup", attributes.getGroupName() ); // 0 is a borderline case, for backwards compatibility it is not overridden by value from defaults // Not just that, but 0 is correct. assertEquals( 0, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( blank, invalid, defaults ); assertEquals( Integer.valueOf( 3333 ), attributes.getUserId() ); assertEquals( "defaultUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 4444 ), attributes.getGroupId() ); assertEquals( "defaultGroup", attributes.getGroupName() ); assertEquals( 0444, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( invalid, invalid, defaults ); assertEquals( Integer.valueOf( 3333 ), attributes.getUserId() ); assertEquals( "defaultUser", attributes.getUserName() ); assertEquals( Integer.valueOf( 4444 ), attributes.getGroupId() ); assertEquals( "defaultGroup", attributes.getGroupName() ); assertEquals( 0444, attributes.getOctalMode() ); // Test cases when invalid defaults should not override blank values attributes = PlexusIoResourceAttributeUtils.mergeAttributes( blank, blank, invalid ); assertNull( attributes.getUserId() ); assertNull( attributes.getUserName() ); assertNull( attributes.getGroupId() ); assertNull( attributes.getGroupName() ); assertEquals( 0, attributes.getOctalMode() ); attributes = PlexusIoResourceAttributeUtils.mergeAttributes( invalid, blank, invalid ); assertNull( attributes.getUserId() ); assertNull( attributes.getUserName() ); assertNull( attributes.getGroupId() ); assertNull( attributes.getGroupName() ); assertEquals( 0, attributes.getOctalMode() ); } private InputStream getStream( String s ) { return this.getClass().getClassLoader().getResourceAsStream( s ); } private Map checkStream( String baseName ) throws Exception { AttributeParser.NumericUserIDAttributeParser numericParser = getNumericParser1nla(); InputStream phase1 = getStream( baseName + "-p1.txt" ); parse( phase1, numericParser ); final AttributeParser.SymbolicUserIDAttributeParser nameBasedParser = getNameBasedParser1la(); InputStream phase2 = getStream( baseName + "-p2.txt" ); parse( phase2, nameBasedParser ); return nameBasedParser.merge( numericParser ); } private Map<String, PlexusIoResourceAttributes> checkStream2( String baseName ) throws Exception { AttributeParser.NumericUserIDAttributeParser numericParser = getNumericParser1nla(); InputStream phase1 = getStream( baseName + "-1nlaR.txt" ); parse( phase1, numericParser ); final AttributeParser.SymbolicUserIDAttributeParser nameBasedParser = getNameBasedParser1la(); InputStream phase2 = getStream( baseName + "-1laR.txt" ); parse( phase2, nameBasedParser ); return nameBasedParser.merge( numericParser ); } private AttributeParser.NumericUserIDAttributeParser getNumericParser1nla() { return new AttributeParser.NumericUserIDAttributeParser( createConsoleLogger() ); } private AttributeParser.SymbolicUserIDAttributeParser getNameBasedParser1la() { return new AttributeParser.SymbolicUserIDAttributeParser( createConsoleLogger() ); } private StreamConsumer createConsoleLogger() { return new StreamConsumer() { public void consumeLine( String line ) { System.out.println(line); } }; } private void parse( InputStream stream, AttributeParser parser ) throws Exception { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( stream ) ); String line = bufferedReader.readLine(); int lineNum = 0; try { while ( line != null ) { parser.consumeLine( line ); line = bufferedReader.readLine(); lineNum++; } } catch ( Exception e ) { Exception exception = new Exception( "At line " + lineNum + "in source:" + line ); exception.initCause( e ); throw e; } } }