/* * Copyright 2006-2012 The Scriptella Project Team. * * 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. */ package scriptella.driver.ldap; import scriptella.AbstractTestCase; import scriptella.driver.ldap.ldif.Entry; import scriptella.driver.ldap.ldif.LdifReader; import scriptella.spi.MockParametersCallbacks; import scriptella.util.ProxyAdapter; import javax.naming.CompoundName; import javax.naming.InvalidNameException; import javax.naming.Name; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import java.io.Reader; import java.io.StringReader; /** * Tests for {@link LdifScript}. * * @author Fyodor Kupolov * @version 1.0 */ public class LdifScriptTest extends AbstractTestCase { private boolean modified; protected void setUp() throws Exception { super.setUp(); modified=false; } public void testGetRelativeDN() throws NamingException { String rootDn = "dc=airius, dc=com"; String rDn = "ou=PD Accountants, ou=Product Development, dc=airius, dc=com"; Name actual = LdifScript.getRelativeDN(rootDn, rDn); Name expected = newName("ou=PD Accountants, ou=Product Development"); assertEquals(expected, actual); //DirContext is boound to a root rootDn = ""; rDn = "dc=com"; actual = LdifScript.getRelativeDN(rootDn, rDn); expected = newName("dc=com"); assertEquals(expected, actual); //rDn doesn't belong to DirContext rootDn = "dc=com"; rDn = "ou=test"; try { LdifScript.getRelativeDN(rootDn, rDn); fail("getRelativeDN works only when rootDn is a part of rDn"); } catch (NamingException e) { //OK } } /** * Tests changetype: moddn */ public void testModifyModdn() throws NamingException { final Entry e = readEntry( "# Rename an entry and move all of its children to a new location in\n" + "# the directory tree (only implemented by LDAPv3 servers).\n" + "dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com\n" + "changetype: moddn\n" + "newrdn: ou=Product Development Accountants\n" + "deleteoldrdn: 0\n" + "newsuperior: ou=Accounting, dc=airius, dc=com\n"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { //do not delete old rdn public void addToEnvironment(String p, Object v) { assertEquals("java.naming.ldap.deleteRDN", p); assertEquals("false", v); } public void removeFromEnvironment(String s) { } public String getNameInNamespace() { return ""; } public void rename(Name oldName, Name newName) throws InvalidNameException { assertEquals(newName("ou=PD Accountants, ou=Product Development, dc=airius, dc=com"), oldName); assertEquals(newName("ou=Product Development Accountants, ou=Accounting, dc=airius, dc=com"), newName); modified=true; } }.getProxy(); LdifScript.modify(mock, e); assertTrue("DirContext was not modified", modified); } /** * Tests changetype: modrdn */ public void testModifyModrdn() throws NamingException { final Entry e = readEntry( "# Rename an entry and move all of its children to a new location in\n" + "# the directory tree (only implemented by LDAPv3 servers).\n" + "dn: ou=PD Accountants, dc=com\n" + "changetype: modrdn\n" + "newrdn: ou=Accountants\n" + "deleteoldrdn: 1\n"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { //Delete old rdn public void addToEnvironment(String p, Object v) { assertEquals("java.naming.ldap.deleteRDN", p); assertEquals("true", v); } public void removeFromEnvironment(String s) { } public String getNameInNamespace() { return ""; } public void rename(Name oldName, Name newName) throws InvalidNameException { assertEquals(newName("ou=PD Accountants, dc=com"), oldName); assertEquals(newName("ou=Accountants, dc=com"), newName); modified=true; } }.getProxy(); LdifScript.modify(mock, e); assertTrue("DirContext was not modified", modified); } /** * Tests add entry * */ public void testModifyAdd() throws NamingException { final Entry e = readEntry( "dn: cn=ldap,dc=scriptella\n" + "cn: ldap\n" + "objectClass: top\n" + "objectClass: driver\n" + "envVars:"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { public String getNameInNamespace() { return "dc=scriptella"; } public DirContext createSubcontext(Name name, Attributes attrs) throws InvalidNameException { assertEquals(newName("cn=ldap"), name); BasicAttributes exp = new BasicAttributes(true); exp.put("cn", "ldap"); final BasicAttribute oc = new BasicAttribute("objectClass"); oc.add("top"); oc.add("driver"); exp.put(oc); exp.put("envVars", null); assertEquals(exp, attrs); modified=true; return null; } }.getProxy(); LdifScript.modify(mock, e); assertTrue("DirContext was not modified", modified); } /** * Tests entry removing */ public void testDelete() throws NamingException { final Entry e = readEntry( "dn: cn=ldap,dc=scriptella\n" + "changetype: delete\n"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { public String getNameInNamespace() { return "dc=scriptella"; } public void destroySubcontext(Name name) throws NamingException { assertEquals(newName("cn=ldap"), name); modified=true; } }.getProxy(); LdifScript.modify(mock, e); assertTrue("DirContext was not modified", modified); } /** * Tests changetype: modify */ public void testModify() throws NamingException { final Entry e = readEntry( "dn: cn=ldap, dc=scriptella\n" + "changetype: modify\n" + "add: postaladdress\n" + "postaladdress: 123 Anystreet\n" + "-\n" + "delete: description\n" + "-\n" + "replace: phone\n" + "phone: 1234\n" + "phone: 5678\n" + "-\n" + "delete: fax\n" + "fax: 1111\n"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { public String getNameInNamespace() { return ""; } public void modifyAttributes(Name name, ModificationItem[] mods) throws InvalidNameException { assertEquals(newName("cn=ldap, dc=scriptella"), name); ModificationItem[] expected = new ModificationItem[4]; expected[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("postaladdress", "123 Anystreet")); expected[1]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("description", null)); BasicAttribute phone = new BasicAttribute("phone"); phone.add("1234");phone.add("5678"); expected[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE, phone); expected[3]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("fax", "1111")); for (int i = 0; i < expected.length; i++) { assertEquals(expected[i].getAttribute(), mods[i].getAttribute()); assertEquals(expected[i].getModificationOp(), mods[i].getModificationOp()); } modified=true; } }.getProxy(); LdifScript.modify(mock, e); assertTrue("DirContext was not modified", modified); } /** * Tests if substituted data goes to LDAP. */ public void testExecute() { Reader ldif = new StringReader( "# Rename an entry and move all of its children to a new location in\n" + "# the directory tree (only implemented by LDAPv3 servers).\n" + "dn: ou=$test, dc=scriptella\n" + "ou: $test\n"); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { public String getNameInNamespace() { return "dc=scriptella"; } public DirContext createSubcontext(Name name, Attributes attrs) throws InvalidNameException { assertEquals(newName("ou=*test*"), name); BasicAttributes exp = new BasicAttributes(true); exp.put("ou", "*test*"); assertEquals(exp, attrs); modified=true; return null; } }.getProxy(); LdifScript ls = new LdifScript(new LdapConnection()); ls.execute(ldif, mock, MockParametersCallbacks.SIMPLE); assertTrue("DirContext was not modified", modified); } /** * Tests error handling */ public void testErrorHadnling() throws NamingException { String ldif = "dn: cn=ldap,dc=scriptella\n" + "changetype: delete\n"; Reader reader = new StringReader(ldif); DirContext mock = new ProxyAdapter<DirContext>(DirContext.class) { public String getNameInNamespace() { return "dc=scriptella"; } public void destroySubcontext(Name name) throws NamingException { throw new NamingException("Failure"); } }.getProxy(); try { LdifScript ls = new LdifScript(new LdapConnection()); ls.execute(reader, mock, MockParametersCallbacks.UNSUPPORTED); } catch (LdapProviderException e) { Throwable ne = e.getNativeException(); assertEquals(NamingException.class, ne.getClass()); assertEquals("Failure", ne.getMessage()); assertEquals(ldif, e.getErrorStatement()); } } /** * @param s ldif * @return entry from ldif */ private static Entry readEntry(String s) { LdifReader lr = new LdifReader(s); return lr.next(); } private static Name newName(String name) throws InvalidNameException { return new CompoundName(name, LdifScript.DN_SYNTAX); } }