ADTest (http://www.microsoft.com/downloads/en/details.aspx?familyid=4814FE3F-92CE-4871-B8A4-99F98B3F4338&displaylang=en) is the LDAP load testing tool to simulate client transaction, it was released few years back (2003). To perform the load testing for Windows 2008 AD LDS, ADTest is the recommended tool (it is the only free LDAP load testing tool that I know – please update this article if there is other (free) tools…).

Another good resource which discusses the usage the ADTest is Active Directory Performance for 64-bit Versions of Windows Server 2003 (http://www.microsoft.com/downloads/en/details.aspx?FamilyID=52e7c3bd-570a-475c-96e0-316dc821e3e7&displaylang=en) whitepaper.

This document consists of 2 part, part 1 and part 2, and structured into the following steps:

  • Plan the test (how many users, directory structures, LDAP operations test)
  • Install and configure AD LDS
  • Install and configure ADTest
  • Create test source file
  • Build directory structures
  • Create users and groups (include populating users to group)
  • LDAP operations test

The second part of this document can be found at http://social.technet.microsoft.com/wiki/contents/articles/windows-2008-ad-lds-load-testing-using-adtest-part-2.aspx

 Plan the Test

In this initial step, agree with the stakeholder on the load testing scenarios, like:

  • How many users: this is the baseline number of load testing, unlike Active Directory; in the case of AD LDS computer objects may not significant factor.
  • Directory structures: Agree on the directory structures with stakeholder, so it can emulate the production directory structures
  • LDAP Operations Test:
    • Authentications: NTLM, Kerberos and LDAP Bind
    • Create objects: Users and Groups
    • Search attribute(s)
    • Update attribute(s)
  • Required infrastructure: which include the Active Directory, AD LDS and client machine

 Install and Configure AD LDS

To install and configure AD LDS for testing, you need to install the Active Directory Lightweight Directory Services role from the Windows 2008 Server Manager.

After the AD LDS role is installed, then AD LDS instance need to be created. Steps for creating the AD LDS instance can be found here: http://technet.microsoft.com/en-us/library/cc770623.aspx

It is recommended to have the following settings:

  • Name instance like AD domain name, if your AD called fabrikam.com, then the AD LDS application partition name can be called dc=fabrikam,dc=corp, this is due to ADTest try to get the first DN section dc=fabrikam for the user who run the ADTest tool authentication.

In my testing environment, I have a domain called fabrikam.com then I have AD LDS partition called dc=liteware,dc=corp, and run the AD LDS remotely (from Windows 7 client). The following error occurred:



The workaround of this issue is to create the AD LDS partition using the DC=fabrikam,DC=corp.

  • Create a domain user account and include it as a member of the Administrators group in the configuration partition, this user will run the ADTest

            

  • For the testing purpose, AD LDS can be excluded from Domain or Local password policies, set the ADAMDisablePasswordPolicies to 1.

            

 Install and Configure ADTest

You can prepare a workstation, and download then install ADTest from http://www.microsoft.com/downloads/en/details.aspx?familyid=4814FE3F-92CE-4871-B8A4-99F98B3F4338&displaylang=en.

The installation process is straight forward. ADTest will be installed in C:\Program Files\Windows Resource Kits\Tools by default.



 Create Test File

The ADTest installation provides the test file called adtest.ats, this file is the text file with all the tests definition. For AD LDS we need to tweak the test file to suit AD LDS testing.

I based my test file from ADTest is Active Directory Performance for 64-bit Versions of Windows Server 2003 whitepaper.

---start test file---

 

//---------------- DEFINES ------------------------//

// [ROOT] is specified on the command line (e.g. -r 32 for [ROOT] = 32)

//Number of users in an organization unit

//this is the default defined range
#define $DefaultRange #(0-2000)

#define $GroupRange #(0-50)

//Users are formatted u0001_0001
#define $Padding ######
#define $UserName u##([ROOT])_$Padding(*)

//Organization Unit Hierarchy
//OU name BaseOU need to be created first

#define $Division ou##([ROOT])_division
#define $Unit ou##([ROOT])_unit
#define $Team ou##([ROOT])_team

#define $DivisionBranch ou=$Division,ou=BaseOU,[DOMAIN]
#define $UnitBranch ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]
#define $TeamBranch ou=$Team,ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]

#define $FQDN cn=$UserName,ou=$Team,ou=$Unit,ou=$Division,ou=BaseOU,[DOMAIN]
#define $BaseOU ou=BaseOU,[DOMAIN]

//OU name Groups under BaseOU need to be created first
#define $GroupOU ou=Groups,ou=BaseOU,[DOMAIN]

//----------------- TESTS ------------------------//

//-------------------- BINDS --------------------------//

Simple_Bind
{
    TEST [BIND]
    LOOP RAND
    RANGE $DefaultRange
    DN $FQDN
    PWD T3stp$ss
}

Simple_Bind_2
{
    TEST [BIND]
    LOOP ONCE
    RANGE $GroupRange
    DN $FQDN
    PWD T3stp$ss
}

//-------------------- UPDATES --------------------------//

Update_1Attr
{
    TEST [MODIFY]
    LOOP RAND
    OP LDAP_MOD_REPLACE
    RANGE $DefaultRange
    DN $FQDN
    ATTR homePhone:###(0-999)-###(0-999)-####(0-9999)
}

Update_10Attr
{
    TEST [MODIFY]
    LOOP RAND
    OP LDAP_MOD_REPLACE
    RANGE $DefaultRange
    DN $FQDN
    ATTR homePhone:###(0-999)-###(0-999)-####(0-9999)
    ATTR pager:###(0-999)-###(0-999)-####(0-9999)
    ATTR mobile:###(0-999)-###(0-999)-####(0-9999)
    ATTR facsimileTelephoneNumber:###(0-999)-###(0-999)-####(0-9999)
    ATTR ipPhone:###(0-999)-###(0-999)-####(0-9999)
    ATTR company:TechnetWiki
    ATTR title:Engineer
    ATTR postOfficeBox:101010
    ATTR streetAddress:1 Jane Doe Street
    ATTR postalCode:101010
}

//-------------------- SEARCHES -----------------------//
Search_Base_1Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $FQDN
    FILTER (objectClass=*)
    SCOPE LDAP_SCOPE_BASE
    ATTR cn
}

Search_Base_10Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $FQDN
    FILTER (objectClass=*)
    SCOPE LDAP_SCOPE_BASE
    ATTR postalCode;postOfficeBox;streetAddress
    ATTR homePhone;ipPhone;telephonenumber;title
}

Search_One_Level_1Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $TeamBranch
    FILTER (userPrincipalName=$UserName)
    SCOPE LDAP_SCOPE_ONELEVEL
    ATTR cn
}

Search_One_Level_10Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $TeamBranch
    FILTER (userPrincipalName=$UserName)
    SCOPE LDAP_SCOPE_ONELEVEL
    ATTR postalCode;postOfficeBox;streetAddress
    ATTR homePhone;ipPhone;telephonenumber;title
}

Search_Subtree_1Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $BaseOU
    FILTER (userPrincipalName=$UserName)
    SCOPE LDAP_SCOPE_SUBTREE
    ATTR cn

}

Search_Subtree_10Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $BaseOU
    FILTER (userPrincipalName=$UserName)
    SCOPE LDAP_SCOPE_SUBTREE
    ATTR postalCode;postOfficeBox;streetAddress
    ATTR homePhone;ipPhone;telephonenumber;title
}

Search_NonIndexed_1Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $BaseOU
    FILTER (department=WikiLDS-####(*))
    SCOPE LDAP_SCOPE_SUBTREE
    ATTR cn
}

Search_NonIndexed_10Attr
{
    TEST [SEARCH]
    LOOP RAND
    RANGE $DefaultRange
    DN $BaseOU
    FILTER (department=wikiLDS-####(*))
    SCOPE LDAP_SCOPE_SUBTREE
    ATTR postalCode;postOfficeBox;streetAddress
    ATTR homePhone;ipPhone;telephonenumber;title
}

//-------------------- SETUP --------------------------//
// Note: Order of these tests is not important but are processed more
// quickly at startup time if you define the inner tests first (e.g., AddDivision)
// and the outer tests second (e.g., NewRoot).

// Use NewRoot to run AddDivision, AddUnit and AddTeam all at once

AddDivision
{
    TEST [ADD]
    LOOP SEQ | ONCE
    OP LDAP_MOD_ADD
    DN $DivisionBranch
    ATTR ObjectClass:organizationalUnit
    ATTR name:$Division
    ATTR instanceType:4
}

AddUnit
{
    TEST [ADD]
    LOOP SEQ | ONCE
    OP LDAP_MOD_ADD
    DN $UnitBranch
    ATTR ObjectClass:organizationalUnit
    ATTR name:$Unit
    ATTR instanceType:4
}

AddTeam
{
    TEST [ADD]
    LOOP SEQ | ONCE
    OP LDAP_MOD_ADD
    DN $TeamBranch
    ATTR ObjectClass:organizationalUnit
    ATTR name:$Team
    ATTR instanceType:4
}

// Typically run adtest -run newroot -root # where # is the root you want
NewRoot
{
    RANGE #(1)
    LOOP SEQ | ONCE
    TEST AddDivision
    TEST AddUnit
    TEST AddTeam
}

AddUser
{
    TEST [ADD]
    LOOP SEQ | ONCE
    OP LDAP_MOD_ADD
    RANGE $DefaultRange
    DN $FQDN
    ATTR ObjectClass:user
    ATTR cn:$UserName
    ATTR userPrincipalName:$UserName
    ATTR adminDescription:Uni
    ATTR adminDisplayName:Uni
    ATTR comment:Uni
    ATTR company:Wiki
    ATTR CountryCode:702
    ATTR department:wikiLDS-$Padding(*)
    ATTR description:Uni
    ATTR displayName:$UserName
    ATTR division:Uni
    ATTR employeeID:Uni
    ATTR facsimileTelephoneNumber:425-38383838
    ATTR givenName:$UserName
    ATTR homePhone:425-83838383
    ATTR ipPhone:425-98989898
    ATTR initials:Uni
    ATTR mobile:425-89898989
    ATTR otherHomePhone:425-10101010
    ATTR otherIpPhone:Uni
    ATTR otherMobile:425-12121212
    ATTR otherPager:425-23232323
    ATTR otherTelephone:425-67676767
    ATTR pager:425-56565656
    ATTR personalTitle:PM
    ATTR physicalDeliveryOfficeName:Uni
    ATTR postalAddress:Uni
    ATTR postalCode:Uni
    ATTR postOfficeBox:Uni
    ATTR roomnumber:1326   
    ATTR streetAddress:Uni
    ATTR telephonenumber:425-78787878
    ATTR title:Engineer
    ATTR userPassword:T3stp$ss
}

AddGroup
{
    TEST [ADD]
    LOOP SEQ|ONCE
    OP LDAP_MOD_ADD
    RANGE $GroupRange
    DN cn=GrpAcc_$Padding(*),$GroupOU
    ATTR ObjectClass:group
    ATTR groupType:2147483650
    ATTR name:GrpAcc_$Padding(*)
    ATTR instanceType:4
}

//Add 50 users to a group
AddMembers
{
    TEST [MODIFY]
    LOOP SEQ|ONCE
    OP LDAP_MOD_ADD
    RANGE $GroupRange
    DN cn=GrpAcc_$Padding([GROUP]),$GroupOU
    ATTR member:$FQDN
}

//Add 2000 users to a group
AddMembers_2
{
    TEST [MODIFY]
    LOOP SEQ|ONCE
    OP LDAP_MOD_ADD
    RANGE $DefaultRange
    DN cn=GrpAcc_$Padding([GROUP]),$GroupOU
    ATTR member:$FQDN
}

---end test file---