Testing LDAP Implementations Emmanuel Lcharny Do who need tests - - PowerPoint PPT Presentation

testing ldap implementations
SMART_READER_LITE
LIVE PREVIEW

Testing LDAP Implementations Emmanuel Lcharny Do who need tests - - PowerPoint PPT Presentation

Testing LDAP Implementations Emmanuel Lcharny Do who need tests anyway ? OSS projects don't need it... We have users ! We have users ! LDAP project phases Initial analysis Development + tests Costs Conformance tests Tests are


slide-1
SLIDE 1

Testing LDAP Implementations

Emmanuel Lécharny

slide-2
SLIDE 2

Do who need tests anyway ?

OSS projects don't need it... We have users !

slide-3
SLIDE 3

We have users !

slide-4
SLIDE 4

LDAP project phases

  • Initial analysis
  • Development + tests
  • Conformance tests

Costs

Tests are costly, and must be run frequently...

slide-5
SLIDE 5

LDAP Tests

  • Unit tests
  • Integration tests
  • Performance tests
slide-6
SLIDE 6

I

slide-7
SLIDE 7

Unit Tests in Java

  • Need a server we can launch
  • Need an API
  • More than that, need some mechanism to speed up tests
slide-8
SLIDE 8

ApacheDS test framework

  • We can start a server using annotations
  • We provide an easy to use API
  • Tests can be run concurrently
  • No need to start/stop or cleanup the server for each test
slide-9
SLIDE 9

Simple test

  • Creation of a DirectoryService
  • Creation of a LdapServer
  • Extends AbstractLdapTestUnit
  • Get an LdapConnection
  • And now we can send requests...
slide-10
SLIDE 10

Code

@RunWith(FrameworkRunner.class class) // Define the DirectoryService @CreateDS() // Define the LDAP protocol layer @CreateLdapServer( transports = { @CreateTransport(protocol = "LDAP") }) public public class class A_SimpleServerTest extends extends AbstractLdapTestUnit { /** * A simple test */ @Test public public void void test() throws throws Exception { LdapServer ldapServer = getLdapServer(); // Get an admin connection on the defined server LdapConnection connection = new new LdapNetworkConnection( "localhost", ldapServer.getPort() ); connection.bind( "uid=admin,ou=system", "secret" ); // Check that we can read an entry assertNotNull( connection.lookup( "ou=system" ) ); // And close the connection connection.close(); } }

slide-11
SLIDE 11

Test with entries injection

  • Same as the previous example
  • Injection of entries with @ApplyLdifs

@ApplyLdifs or @ApplyLdifFiles @ApplyLdifFiles

slide-12
SLIDE 12

Code

@ApplyLdifs( // Inject an entry { // Entry # 1 "dn: uid=elecharny,ou=users,ou=system", "objectClass: uidObject", "objectClass: person", "objectClass: top", "uid: elecharny", "cn: Emmanuel Lécharny", "sn: lecharny", "userPassword: emmanuel" }) @CreateDS() // Define the DirectoryService @CreateLdapServer( // Define the LDAP protocol layer transports = { @CreateTransport(protocol = "LDAP") }) public public class class B_LdifEntryServerTest extends extends AbstractLdapTestUnit { /** * A test where we bind using the added entry credentials */ @Test public public void void testBindUser() throws throws Exception { // Get a connection (not bound yet) on the server LdapConnection connection = getWiredConnection( getLdapServer() ); connection.bind( "uid=elecharny,ou=users,ou=system", "emmanuel" ); // Check that we can read an entry assertNotNull( connection.lookup( "uid=elecharny,ou=users,ou=system" ) ); // And close the connection connection.close(); } }

slide-13
SLIDE 13

Test with partition creation

  • Creation of a DirectoryService
  • Creation of a Partition
  • Creation of indexes
  • Etc...
slide-14
SLIDE 14

Code

@RunWith(FrameworkRunner.class class) // Define the DirectoryService @CreateDS( partitions = { @CreatePartition( name = "example", suffix = "dc=example,dc=com", contextEntry = @ContextEntry( entryLdif = "dn: dc=example,dc=com\n" + "dc: example\n" + "objectClass: top\n" + "objectClass: domain\n\n" ), indexes = { @CreateIndex( attribute = "objectClass" ), @CreateIndex( attribute = "dc" ), @CreateIndex( attribute = "ou" ) } ) }) @CreateLdapServer( // Define the LDAP protocol layer transports = { @CreateTransport(protocol = "LDAP") }) public public class class D_ServerWithPartitionTest extends extends AbstractLdapTestUnit { @Test public public void void test() throws throws Exception { // Get an admin connection on the defined server LdapConnection connection = getWiredConnection( getLdapServer(), "uid=admin,ou=system", "secret" ); // Check that we can read the Example context entry assertNotNull( connection.lookup( "dc=example,dc=com" ) ); ...

slide-15
SLIDE 15

Saving start/stop delays

  • No need to start a fresh server for each test
  • No need to revert the modifjcations when the test is done
  • Automatic rollback
  • OTOH, kills concurrent tests...
slide-16
SLIDE 16

Defjning more than one server

  • May be needed
  • Can be associated to a suite, a class or a method
slide-17
SLIDE 17

Modifying the schema

  • Easy to modify
  • Use @ApplyLdifs or @ApplyLidfFiles for that

purpose

  • Will be reverted when the test will end, as usual
slide-18
SLIDE 18

II

slide-19
SLIDE 19

JMeter

  • User friendly GUI
  • Tests can be exported and executed
  • Remote agents can be used
  • No code needed
slide-20
SLIDE 20

III

slide-21
SLIDE 21

API

  • Schema aware
  • Easy to use
  • Deal locally with comparisons
slide-22
SLIDE 22

Problem

@ApplyLdifs( { // Entry # 1 "dn: cn=Test Lookup,ou=system", "objectClass: person", "cn: Test Lookup", "sn: sn test" }) public void testLookupCn() throws Exception { LdapConnection connection = LdapConnection connection = getWiredConnection( getLdapServer(), "uid=admin,ou=system", "secret" ); Entry entry = connection.lookup( Entry entry = connection.lookup( "cn=test lookup,ou=system", "cn" ); assertNotNull( entry ); // Check that we don't have any operational attributes : // We should have only 3 attributes : objectClass, cn and sn assertEquals( 1, entry.size() ); // Check that all the user attributes are present assertTrue( entry.contains( "cn", "Test Lookup" ) ); assertFalse( entry.contains( "cn", "test lookup" ) ); assertFalse( entry.contains( "2.5.4.3", "test lookup" ) ); assertFalse( entry.contains( "CN", " test LOOKUP " ) ); } }

slide-23
SLIDE 23

Solution

@ApplyLdifs( { // Entry # 1 "dn: cn=Test Lookup,ou=system", "objectClass: person", "cn: Test Lookup", "sn: sn test" }) public void testLookupCn() throws Exception { LdapConnection connection = LdapConnection connection = getWiredConnection( getLdapServer(), "uid=admin,ou=system", "secret" ); // Make the connection schema aware connection.loadSchema(); Entry entry = connection.lookup( Entry entry = connection.lookup( "cn=test lookup,ou=system", "cn" ); assertNotNull( entry ); // Check that we don't have any operational attributes : // We should have only 3 attributes : objectClass, cn and sn assertEquals( 1, entry.size() ); // Check that all the user attributes are present assertTrue( entry.contains( "cn", "Test Lookup" ) ); assertTrue( entry.contains( "cn", "test lookup" ) ); assertTrue( entry.contains( "2.5.4.3", "test lookup" ) ); assertTrue( entry.contains( "CN", " test LOOKUP " ) ); } }

slide-24
SLIDE 24

IV

slide-25
SLIDE 25

Future

  • Use Studio to register scenarii
  • 'Reboot' Slamd effort (or design a new tool)
  • Provide a Groovy LDAP API
  • Add LDAP assertions
  • Make the Java tests able to start another server
  • LDAPUnit : a dedicated LDAP test framework
slide-26
SLIDE 26

Thanks !

slide-27
SLIDE 27

Q/R