001    /*
002     * Copyright 2011-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2011-2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.util;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Arrays;
027    import java.util.Collection;
028    import java.util.List;
029    
030    import com.unboundid.ldap.matchingrules.DistinguishedNameMatchingRule;
031    import com.unboundid.ldap.sdk.Attribute;
032    import com.unboundid.ldap.sdk.Control;
033    import com.unboundid.ldap.sdk.DN;
034    import com.unboundid.ldap.sdk.Entry;
035    import com.unboundid.ldap.sdk.Filter;
036    import com.unboundid.ldap.sdk.LDAPConnection;
037    import com.unboundid.ldap.sdk.LDAPException;
038    import com.unboundid.ldap.sdk.LDAPInterface;
039    import com.unboundid.ldap.sdk.LDAPRequest;
040    import com.unboundid.ldap.sdk.LDAPResult;
041    import com.unboundid.ldap.sdk.LDAPSearchException;
042    import com.unboundid.ldap.sdk.RDN;
043    import com.unboundid.ldap.sdk.ResultCode;
044    import com.unboundid.ldap.sdk.SearchResult;
045    import com.unboundid.ldap.sdk.SearchResultEntry;
046    import com.unboundid.ldap.sdk.SearchResultReference;
047    import com.unboundid.ldap.sdk.SearchScope;
048    
049    import static com.unboundid.util.UtilityMessages.*;
050    
051    
052    
053    /**
054     * This class provides a number of convenience methods that can be used to help
055     * write test cases for directory-enabled applications.
056     */
057    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
058    public final class LDAPTestUtils
059    {
060      /**
061       * Ensure that this utility class cannot be instantiated.
062       */
063      private LDAPTestUtils()
064      {
065        // No implementation required.
066      }
067    
068    
069    
070      /**
071       * Generates a domain entry with the provided information.  It will include
072       * the top and domain object classes and will use dc as the RDN attribute.  It
073       * may optionally include additional attributes.
074       *
075       * @param  name                  The name for the domain, which will be used
076       *                               as the value of the "dc" attribute.  It must
077       *                               not be {@code null}.
078       * @param  parentDN              The DN of the entry below which the new
079       *                               entry should be placed.  It may be
080       *                               {@code null} if the new entry should not have
081       *                               a parent.
082       * @param  additionalAttributes  A set of additional attributes to include in
083       *                               the generated entry.  It may be {@code null}
084       *                               or empty if no additional attributes should
085       *                               be included.
086       *
087       * @return  The generated entry.
088       */
089      public static Entry generateDomainEntry(final String name,
090                               final String parentDN,
091                               final Attribute... additionalAttributes)
092      {
093        return generateDomainEntry(name, parentDN,
094             StaticUtils.toList(additionalAttributes));
095      }
096    
097    
098    
099      /**
100       * Generates a domain entry with the provided information.  It will include
101       * the top and domain object classes and will use dc as the RDN attribute.  It
102       * may optionally include additional attributes.
103       *
104       * @param  name                  The name for the domain, which will be used
105       *                               as the value of the "dc" attribute.  It must
106       *                               not be {@code null}.
107       * @param  parentDN              The DN of the entry below which the new
108       *                               entry should be placed.  It may be
109       *                               {@code null} if the new entry should not have
110       *                               a parent.
111       * @param  additionalAttributes  A set of additional attributes to include in
112       *                               the generated entry.  It may be {@code null}
113       *                               or empty if no additional attributes should
114       *                               be included.
115       *
116       * @return  The generated entry.
117       */
118      public static Entry generateDomainEntry(final String name,
119                               final String parentDN,
120                               final Collection<Attribute> additionalAttributes)
121      {
122        return generateEntry("dc", name, parentDN, new String[] { "top", "domain" },
123             additionalAttributes);
124      }
125    
126    
127    
128      /**
129       * Generates an organization entry with the provided information.  It will
130       * include the top and organization object classes and will use o as the RDN
131       * attribute.  It may optionally include additional attributes.
132       *
133       * @param  name                  The name for the organization, which will be
134       *                               used as the value of the "o" attribute.  It
135       *                               must not be {@code null}.
136       * @param  parentDN              The DN of the entry below which the new
137       *                               entry should be placed.  It may be
138       *                               {@code null} if the new entry should not have
139       *                               a parent.
140       * @param  additionalAttributes  A set of additional attributes to include in
141       *                               the generated entry.  It may be {@code null}
142       *                               or empty if no additional attributes should
143       *                               be included.
144       *
145       * @return  The generated entry.
146       */
147      public static Entry generateOrgEntry(final String name, final String parentDN,
148                               final Attribute... additionalAttributes)
149      {
150        return generateOrgEntry(name, parentDN,
151             StaticUtils.toList(additionalAttributes));
152      }
153    
154    
155    
156      /**
157       * Generates an organization entry with the provided information.  It will
158       * include the top and organization object classes and will use o as the RDN
159       * attribute.  It may optionally include additional attributes.
160       *
161       * @param  name                  The name for the organization, which will be
162       *                               used as the value of the "o" attribute.  It
163       *                               must not be {@code null}.
164       * @param  parentDN              The DN of the entry below which the new
165       *                               entry should be placed.  It may be
166       *                               {@code null} if the new entry should not have
167       *                               a parent.
168       * @param  additionalAttributes  A set of additional attributes to include in
169       *                               the generated entry.  It may be {@code null}
170       *                               or empty if no additional attributes should
171       *                               be included.
172       *
173       * @return  The generated entry.
174       */
175      public static Entry generateOrgEntry(final String name, final String parentDN,
176                               final Collection<Attribute> additionalAttributes)
177      {
178        return generateEntry("o", name, parentDN,
179             new String[] { "top", "organization" },
180             additionalAttributes);
181      }
182    
183    
184    
185      /**
186       * Generates an organizationalUnit entry with the provided information.  It
187       * will include the top and organizationalUnit object classes and will use ou
188       * as the RDN attribute.  It may optionally include additional attributes.
189       *
190       * @param  name                  The name for the organizationalUnit, which
191       *                               will be used as the value of the "ou"
192       *                               attribute.  It must not be {@code null}.
193       * @param  parentDN              The DN of the entry below which the new
194       *                               entry should be placed.  It may be
195       *                               {@code null} if the new entry should not have
196       *                               a parent.
197       * @param  additionalAttributes  A set of additional attributes to include in
198       *                               the generated entry.  It may be {@code null}
199       *                               or empty if no additional attributes should
200       *                               be included.
201       *
202       * @return  The generated entry.
203       */
204      public static Entry generateOrgUnitEntry(final String name,
205                               final String parentDN,
206                               final Attribute... additionalAttributes)
207      {
208        return generateOrgUnitEntry(name, parentDN,
209             StaticUtils.toList(additionalAttributes));
210      }
211    
212    
213    
214      /**
215       * Generates an organizationalUnit entry with the provided information.  It
216       * will include the top and organizationalUnit object classes and will use ou
217       * as the RDN attribute.  It may optionally include additional attributes.
218       *
219       * @param  name                  The name for the organizationalUnit, which
220       *                               will be used as the value of the "ou"
221       *                               attribute.  It must not be {@code null}.
222       * @param  parentDN              The DN of the entry below which the new
223       *                               entry should be placed.  It may be
224       *                               {@code null} if the new entry should not have
225       *                               a parent.
226       * @param  additionalAttributes  A set of additional attributes to include in
227       *                               the generated entry.  It may be {@code null}
228       *                               or empty if no additional attributes should
229       *                               be included.
230       *
231       * @return  The generated entry.
232       */
233      public static Entry generateOrgUnitEntry(final String name,
234                               final String parentDN,
235                               final Collection<Attribute> additionalAttributes)
236      {
237        return generateEntry("ou", name, parentDN,
238             new String[] { "top", "organizationalUnit" },
239             additionalAttributes);
240      }
241    
242    
243    
244      /**
245       * Generates a country entry with the provided information.  It will include
246       * the top and country object classes and will use c as the RDN attribute.  It
247       * may optionally include additional attributes.
248       *
249       * @param  name                  The name for the country (typically a
250       *                               two-character country code), which will be
251       *                               used as the value of the "c" attribute.  It
252       *                               must not be {@code null}.
253       * @param  parentDN              The DN of the entry below which the new
254       *                               entry should be placed.  It may be
255       *                               {@code null} if the new entry should not have
256       *                               a parent.
257       * @param  additionalAttributes  A set of additional attributes to include in
258       *                               the generated entry.  It may be {@code null}
259       *                               or empty if no additional attributes should
260       *                               be included.
261       *
262       * @return  The generated entry.
263       */
264      public static Entry generateCountryEntry(final String name,
265                               final String parentDN,
266                               final Attribute... additionalAttributes)
267      {
268        return generateCountryEntry(name, parentDN,
269             StaticUtils.toList(additionalAttributes));
270      }
271    
272    
273    
274      /**
275       * Generates a country entry with the provided information.  It will include
276       * the top and country object classes and will use c as the RDN attribute.  It
277       * may optionally include additional attributes.
278       *
279       * @param  name                  The name for the country (typically a
280       *                               two-character country code), which will be
281       *                               used as the value of the "c" attribute.  It
282       *                               must not be {@code null}.
283       * @param  parentDN              The DN of the entry below which the new
284       *                               entry should be placed.  It may be
285       *                               {@code null} if the new entry should not have
286       *                               a parent.
287       * @param  additionalAttributes  A set of additional attributes to include in
288       *                               the generated entry.  It may be {@code null}
289       *                               or empty if no additional attributes should
290       *                               be included.
291       *
292       * @return  The generated entry.
293       */
294      public static Entry generateCountryEntry(final String name,
295                               final String parentDN,
296                               final Collection<Attribute> additionalAttributes)
297      {
298        return generateEntry("c", name, parentDN,
299             new String[] { "top", "country" },
300             additionalAttributes);
301      }
302    
303    
304    
305      /**
306       * Generates a user entry with the provided information.  It will include the
307       * top, person, organizationalPerson, and inetOrgPerson object classes, will
308       * use uid as the RDN attribute, and will have givenName, sn, and cn
309       * attributes.  It may optionally include additional attributes.
310       *
311       * @param  uid                   The value to use for the "uid: attribute.  It
312       *                               must not be {@code null}.
313       * @param  parentDN              The DN of the entry below which the new
314       *                               entry should be placed.  It may be
315       *                               {@code null} if the new entry should not have
316       *                               a parent.
317       * @param  firstName             The first name for the user.  It must not be
318       *                               {@code null}.
319       * @param  lastName              The last name for the user.  It must not be
320       *                               {@code null}.
321       * @param  password              The password for the user.  It may be
322       *                               {@code null} if the user should not have a
323       *                               password.
324       * @param  additionalAttributes  A set of additional attributes to include in
325       *                               the generated entry.  It may be {@code null}
326       *                               or empty if no additional attributes should
327       *                               be included.
328       *
329       * @return  The generated entry.
330       */
331      public static Entry generateUserEntry(final String uid, final String parentDN,
332                               final String firstName, final String lastName,
333                               final String password,
334                               final Attribute... additionalAttributes)
335      {
336        return generateUserEntry(uid, parentDN, firstName, lastName, password,
337             StaticUtils.toList(additionalAttributes));
338      }
339    
340    
341    
342      /**
343       * Generates a user entry with the provided information.  It will include the
344       * top, person, organizationalPerson, and inetOrgPerson object classes, will
345       * use uid as the RDN attribute, and will have givenName, sn, and cn
346       * attributes.  It may optionally include additional attributes.
347       *
348       * @param  uid                   The value to use for the "uid: attribute.  It
349       *                               must not be {@code null}.
350       * @param  parentDN              The DN of the entry below which the new
351       *                               entry should be placed.  It may be
352       *                               {@code null} if the new entry should not have
353       *                               a parent.
354       * @param  firstName             The first name for the user.  It must not be
355       *                               {@code null}.
356       * @param  lastName              The last name for the user.  It must not be
357       *                               {@code null}.
358       * @param  password              The password for the user.  It may be
359       *                               {@code null} if the user should not have a
360       *                               password.
361       * @param  additionalAttributes  A set of additional attributes to include in
362       *                               the generated entry.  It may be {@code null}
363       *                               or empty if no additional attributes should
364       *                               be included.
365       *
366       * @return  The generated entry.
367       */
368      public static Entry generateUserEntry(final String uid, final String parentDN,
369                               final String firstName, final String lastName,
370                               final String password,
371                               final Collection<Attribute> additionalAttributes)
372      {
373        final List<Attribute> attrList = new ArrayList<Attribute>(4);
374        attrList.add(new Attribute("givenName", firstName));
375        attrList.add(new Attribute("sn", lastName));
376        attrList.add(new Attribute("cn", firstName + ' ' + lastName));
377    
378        if (password != null)
379        {
380          attrList.add(new Attribute("userPassword", password));
381        }
382    
383        if (additionalAttributes != null)
384        {
385          attrList.addAll(additionalAttributes);
386        }
387    
388        final String[] objectClasses =
389        {
390          "top",
391          "person",
392          "organizationalPerson",
393          "inetOrgPerson",
394        };
395    
396        return generateEntry("uid", uid, parentDN, objectClasses, attrList);
397      }
398    
399    
400    
401      /**
402       * Generates a group entry with the provided information.  It will include
403       * the top and groupOfNames object classes and will use cn as the RDN
404       * attribute.
405       *
406       * @param  name       The name for the group, which will be used as the value
407       *                    of the "cn" attribute.  It must not be {@code null}.
408       * @param  parentDN   The DN of the entry below which the new entry should be
409       *                    placed.  It may be {@code null} if the new entry should
410       *                    not have a parent.
411       * @param  memberDNs  The DNs of the users that should be listed as members of
412       *                    the group.
413       *
414       * @return  The generated entry.
415       */
416      public static Entry generateGroupOfNamesEntry(final String name,
417                                                    final String parentDN,
418                                                    final String... memberDNs)
419      {
420        return generateGroupOfNamesEntry(name, parentDN,
421             StaticUtils.toList(memberDNs));
422      }
423    
424    
425    
426      /**
427       * Generates a group entry with the provided information.  It will include
428       * the top and groupOfNames object classes and will use cn as the RDN
429       * attribute.
430       *
431       * @param  name       The name for the group, which will be used as the value
432       *                    of the "cn" attribute.  It must not be {@code null}.
433       * @param  parentDN   The DN of the entry below which the new entry should be
434       *                    placed.  It may be {@code null} if the new entry should
435       *                    not have a parent.
436       * @param  memberDNs  The DNs of the users that should be listed as members of
437       *                    the group.
438       *
439       * @return  The generated entry.
440       */
441      public static Entry generateGroupOfNamesEntry(final String name,
442                               final String parentDN,
443                               final Collection<String> memberDNs)
444      {
445        final ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
446        attrList.add(new Attribute("member",
447             DistinguishedNameMatchingRule.getInstance(), memberDNs));
448    
449        return generateEntry("cn", name, parentDN,
450             new String[] { "top", "groupOfNames" }, attrList);
451      }
452    
453    
454    
455      /**
456       * Generates a group entry with the provided information.  It will include
457       * the top and groupOfUniqueNames object classes and will use cn as the RDN
458       * attribute.
459       *
460       * @param  name       The name for the group, which will be used as the value
461       *                    of the "cn" attribute.  It must not be {@code null}.
462       * @param  parentDN   The DN of the entry below which the new entry should be
463       *                    placed.  It may be {@code null} if the new entry should
464       *                    not have a parent.
465       * @param  memberDNs  The DNs of the users that should be listed as members of
466       *                    the group.
467       *
468       * @return  The generated entry.
469       */
470      public static Entry generateGroupOfUniqueNamesEntry(final String name,
471                                                          final String parentDN,
472                                                          final String... memberDNs)
473      {
474        return generateGroupOfUniqueNamesEntry(name, parentDN,
475             StaticUtils.toList(memberDNs));
476      }
477    
478    
479    
480      /**
481       * Generates a group entry with the provided information.  It will include
482       * the top and groupOfUniqueNames object classes and will use cn as the RDN
483       * attribute.
484       *
485       * @param  name       The name for the group, which will be used as the value
486       *                    of the "cn" attribute.  It must not be {@code null}.
487       * @param  parentDN   The DN of the entry below which the new entry should be
488       *                    placed.  It may be {@code null} if the new entry should
489       *                    not have a parent.
490       * @param  memberDNs  The DNs of the users that should be listed as members of
491       *                    the group.
492       *
493       * @return  The generated entry.
494       */
495      public static Entry generateGroupOfUniqueNamesEntry(final String name,
496                               final String parentDN,
497                               final Collection<String> memberDNs)
498      {
499        final ArrayList<Attribute> attrList = new ArrayList<Attribute>(1);
500        attrList.add(new Attribute("uniqueMember",
501             DistinguishedNameMatchingRule.getInstance(), memberDNs));
502    
503        return generateEntry("cn", name, parentDN,
504             new String[] { "top", "groupOfUniqueNames" }, attrList);
505      }
506    
507    
508    
509      /**
510       * Generates entry with the provided information.
511       *
512       * @param  rdnAttr               The name of the attribute to use for the RDN.
513       * @param  rdnValue              The value of the attribute to use for the
514       *                               RDN.
515       * @param  parentDN              The DN of the entry below which the new
516       *                               entry should be placed.  It may be
517       *                               {@code null} if the new entry should not have
518       *                               a parent.
519       * @param  objectClasses         The object class values to include in the
520       *                               entry.
521       * @param  additionalAttributes  A set of additional attributes to include in
522       *                               the generated entry.  It may be {@code null}
523       *                               or empty if no additional attributes should
524       *                               be included.
525       *
526       * @return  The generated entry.
527       */
528      private static Entry generateEntry(final String rdnAttr,
529                                final String rdnValue, final String parentDN,
530                                final String[] objectClasses,
531                                final Collection<Attribute> additionalAttributes)
532      {
533        final RDN rdn = new RDN(rdnAttr, rdnValue);
534    
535        final String dn;
536        if ((parentDN == null) || (parentDN.trim().length() == 0))
537        {
538          dn = rdn.toString();
539        }
540        else
541        {
542          dn = rdn.toString() + ',' + parentDN;
543        }
544    
545        final Entry entry = new Entry(dn,
546             new Attribute("objectClass", objectClasses),
547             new Attribute(rdnAttr, rdnValue));
548    
549        if (additionalAttributes != null)
550        {
551          for (final Attribute a : additionalAttributes)
552          {
553            entry.addAttribute(a);
554          }
555        }
556    
557        return entry;
558      }
559    
560    
561    
562      /**
563       * Indicates whether the specified entry exists in the server.
564       *
565       * @param  conn  The connection to use to communicate with the directory
566       *               server.
567       * @param  dn    The DN of the entry for which to make the determination.
568       *
569       * @return  {@code true} if the entry exists, or {@code false} if not.
570       *
571       * @throws  LDAPException  If a problem is encountered while trying to
572       *                         communicate with the directory server.
573       */
574      public static boolean entryExists(final LDAPInterface conn, final String dn)
575             throws LDAPException
576      {
577        return (conn.getEntry(dn, "1.1") != null);
578      }
579    
580    
581    
582      /**
583       * Indicates whether the specified entry exists in the server and matches the
584       * given filter.
585       *
586       * @param  conn    The connection to use to communicate with the directory
587       *                 server.
588       * @param  dn      The DN of the entry for which to make the determination.
589       * @param  filter  The filter the entry is expected to match.
590       *
591       * @return  {@code true} if the entry exists and matches the specified filter,
592       *          or {@code false} if not.
593       *
594       * @throws  LDAPException  If a problem is encountered while trying to
595       *                         communicate with the directory server.
596       */
597      public static boolean entryExists(final LDAPInterface conn, final String dn,
598                                        final String filter)
599             throws LDAPException
600      {
601        try
602        {
603          final SearchResult searchResult =
604               conn.search(dn, SearchScope.BASE, filter, "1.1");
605          return (searchResult.getEntryCount() == 1);
606        }
607        catch (final LDAPException le)
608        {
609          if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
610          {
611            return false;
612          }
613          else
614          {
615            throw le;
616          }
617        }
618      }
619    
620    
621    
622      /**
623       * Indicates whether the specified entry exists in the server.  This will
624       * return {@code true} only if the target entry exists and contains all values
625       * for all attributes of the provided entry.  The entry will be allowed to
626       * have attribute values not included in the provided entry.
627       *
628       * @param  conn   The connection to use to communicate with the directory
629       *                server.
630       * @param  entry  The entry to compare against the directory server.
631       *
632       * @return  {@code true} if the entry exists in the server and is a superset
633       *          of the provided entry, or {@code false} if not.
634       *
635       * @throws  LDAPException  If a problem is encountered while trying to
636       *                         communicate with the directory server.
637       */
638      public static boolean entryExists(final LDAPInterface conn, final Entry entry)
639             throws LDAPException
640      {
641        final Collection<Attribute> attrs = entry.getAttributes();
642    
643        final List<Filter> comps = new ArrayList<Filter>(attrs.size());
644        for (final Attribute a : attrs)
645        {
646          for (final byte[] value : a.getValueByteArrays())
647          {
648            comps.add(Filter.createEqualityFilter(a.getName(), value));
649          }
650        }
651    
652        try
653        {
654          final SearchResult searchResult = conn.search(entry.getDN(),
655               SearchScope.BASE, Filter.createANDFilter(comps), "1.1");
656          return (searchResult.getEntryCount() == 1);
657        }
658        catch (final LDAPException le)
659        {
660          if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
661          {
662            return false;
663          }
664          else
665          {
666            throw le;
667          }
668        }
669      }
670    
671    
672    
673      /**
674       * Ensures that an entry with the provided DN exists in the directory.
675       *
676       * @param  conn  The connection to use to communicate with the directory
677       *               server.
678       * @param  dn    The DN of the entry for which to make the determination.
679       *
680       * @throws  LDAPException  If a problem is encountered while trying to
681       *                         communicate with the directory server.
682       *
683       * @throws  AssertionError  If the target entry does not exist.
684       */
685      public static void assertEntryExists(final LDAPInterface conn,
686                                           final String dn)
687             throws LDAPException, AssertionError
688      {
689        if (conn.getEntry(dn, "1.1") == null)
690        {
691          throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
692        }
693      }
694    
695    
696    
697      /**
698       * Ensures that an entry with the provided DN exists in the directory.
699       *
700       * @param  conn    The connection to use to communicate with the directory
701       *                 server.
702       * @param  dn      The DN of the entry for which to make the determination.
703       * @param  filter  A filter that the target entry must match.
704       *
705       * @throws  LDAPException  If a problem is encountered while trying to
706       *                         communicate with the directory server.
707       *
708       * @throws  AssertionError  If the target entry does not exist or does not
709       *                          match the provided filter.
710       */
711      public static void assertEntryExists(final LDAPInterface conn,
712                                           final String dn, final String filter)
713             throws LDAPException, AssertionError
714      {
715        try
716        {
717          final SearchResult searchResult =
718               conn.search(dn, SearchScope.BASE, filter, "1.1");
719          if (searchResult.getEntryCount() == 0)
720          {
721            throw new AssertionError(ERR_TEST_ENTRY_DOES_NOT_MATCH_FILTER.get(dn,
722                 filter));
723          }
724        }
725        catch (final LDAPException le)
726        {
727          if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
728          {
729            throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
730          }
731          else
732          {
733            throw le;
734          }
735        }
736      }
737    
738    
739    
740      /**
741       * Ensures that an entry exists in the directory with the same DN and all
742       * attribute values contained in the provided entry.  The server entry may
743       * contain additional attributes and/or attribute values not included in the
744       * provided entry.
745       *
746       * @param  conn   The connection to use to communicate with the directory
747       *                server.
748       * @param  entry  The entry expected to be present in the directory server.
749       *
750       * @throws  LDAPException  If a problem is encountered while trying to
751       *                         communicate with the directory server.
752       *
753       * @throws  AssertionError  If the target entry does not exist or does not
754       *                          match the provided filter.
755       */
756      public static void assertEntryExists(final LDAPInterface conn,
757                                           final Entry entry)
758             throws LDAPException, AssertionError
759      {
760        // First, try to make the determination with a single search.  Only if
761        // this returns false will we perform a more thorough test to construct the
762        // most useful error message possible.
763        if (entryExists(conn, entry))
764        {
765          return;
766        }
767    
768        final Collection<Attribute> attributes = entry.getAttributes();
769        final List<String> messages = new ArrayList<String>(attributes.size());
770    
771        for (final Attribute a : attributes)
772        {
773          // Determine whether the attribute is present in the entry.
774          try
775          {
776            final SearchResult searchResult = conn.search(entry.getDN(),
777                 SearchScope.BASE, Filter.createPresenceFilter(a.getName()), "1.1");
778            if (searchResult.getEntryCount() == 0)
779            {
780              messages.add(ERR_TEST_ATTR_MISSING.get(entry.getDN(), a.getName()));
781              continue;
782            }
783          }
784          catch (final LDAPException le)
785          {
786            if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
787            {
788              throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(entry.getDN()));
789            }
790            else
791            {
792              throw le;
793            }
794          }
795    
796          for (final byte[] value : a.getValueByteArrays())
797          {
798            final SearchResult searchResult = conn.search(entry.getDN(),
799                 SearchScope.BASE, Filter.createEqualityFilter(a.getName(), value),
800                 "1.1");
801            if (searchResult.getEntryCount() == 0)
802            {
803              messages.add(ERR_TEST_VALUE_MISSING.get(entry.getDN(), a.getName(),
804                   StaticUtils.toUTF8String(value)));
805            }
806          }
807        }
808    
809        if (! messages.isEmpty())
810        {
811          throw new AssertionError(StaticUtils.concatenateStrings(messages));
812        }
813      }
814    
815    
816    
817      /**
818       * Retrieves a list containing the DNs of the entries which are missing from
819       * the directory server.
820       *
821       * @param  conn  The connection to use to communicate with the directory
822       *               server.
823       * @param  dns   The DNs of the entries to try to find in the server.
824       *
825       * @return  A list containing all of the provided DNs that were not found in
826       *          the server, or an empty list if all entries were found.
827       *
828       * @throws  LDAPException  If a problem is encountered while trying to
829       *                         communicate with the directory server.
830       */
831      public static List<String> getMissingEntryDNs(final LDAPInterface conn,
832                                                    final String... dns)
833             throws LDAPException
834      {
835        return getMissingEntryDNs(conn, StaticUtils.toList(dns));
836      }
837    
838    
839    
840      /**
841       * Retrieves a list containing the DNs of the entries which are missing from
842       * the directory server.
843       *
844       * @param  conn  The connection to use to communicate with the directory
845       *               server.
846       * @param  dns   The DNs of the entries to try to find in the server.
847       *
848       * @return  A list containing all of the provided DNs that were not found in
849       *          the server, or an empty list if all entries were found.
850       *
851       * @throws  LDAPException  If a problem is encountered while trying to
852       *                         communicate with the directory server.
853       */
854      public static List<String> getMissingEntryDNs(final LDAPInterface conn,
855                                                    final Collection<String> dns)
856             throws LDAPException
857      {
858        final List<String> missingDNs = new ArrayList<String>(dns.size());
859    
860        for (final String dn : dns)
861        {
862          if (conn.getEntry(dn, "1.1") == null)
863          {
864            missingDNs.add(dn);
865          }
866        }
867    
868        return missingDNs;
869      }
870    
871    
872    
873      /**
874       * Ensures that all of the entries with the provided DNs exist in the
875       * directory.
876       *
877       * @param  conn  The connection to use to communicate with the directory
878       *               server.
879       * @param  dns   The DNs of the entries for which to make the determination.
880       *
881       * @throws  LDAPException  If a problem is encountered while trying to
882       *                         communicate with the directory server.
883       *
884       * @throws  AssertionError  If any of the target entries does not exist.
885       */
886      public static void assertEntriesExist(final LDAPInterface conn,
887                                            final String... dns)
888             throws LDAPException, AssertionError
889      {
890        assertEntriesExist(conn, StaticUtils.toList(dns));
891      }
892    
893    
894    
895      /**
896       * Ensures that all of the entries with the provided DNs exist in the
897       * directory.
898       *
899       * @param  conn  The connection to use to communicate with the directory
900       *               server.
901       * @param  dns   The DNs of the entries for which to make the determination.
902       *
903       * @throws  LDAPException  If a problem is encountered while trying to
904       *                         communicate with the directory server.
905       *
906       * @throws  AssertionError  If any of the target entries does not exist.
907       */
908      public static void assertEntriesExist(final LDAPInterface conn,
909                                            final Collection<String> dns)
910             throws LDAPException, AssertionError
911      {
912        final List<String> missingDNs = getMissingEntryDNs(conn, dns);
913        if (missingDNs.isEmpty())
914        {
915          return;
916        }
917    
918        final ArrayList<String> msgList = new ArrayList<String>(missingDNs.size());
919        for (final String dn : missingDNs)
920        {
921          msgList.add(ERR_TEST_ENTRY_MISSING.get(dn));
922        }
923    
924        throw new AssertionError(StaticUtils.concatenateStrings(msgList));
925      }
926    
927    
928    
929      /**
930       * Retrieves a list containing all of the named attributes which do not exist
931       * in the target entry.
932       *
933       * @param  conn            The connection to use to communicate with the
934       *                         directory server.
935       * @param  dn              The DN of the entry to examine.
936       * @param  attributeNames  The names of the attributes expected to be present
937       *                         in the target entry.
938       *
939       * @return  A list containing the names of the attributes which were not
940       *          present in the target entry, an empty list if all specified
941       *          attributes were found in the entry, or {@code null} if the target
942       *          entry does not exist.
943       *
944       * @throws  LDAPException  If a problem is encountered while trying to
945       *                         communicate with the directory server.
946       */
947      public static List<String> getMissingAttributeNames(final LDAPInterface conn,
948                                      final String dn,
949                                      final String... attributeNames)
950             throws LDAPException
951      {
952        return getMissingAttributeNames(conn, dn,
953             StaticUtils.toList(attributeNames));
954      }
955    
956    
957    
958      /**
959       * Retrieves a list containing all of the named attributes which do not exist
960       * in the target entry.
961       *
962       * @param  conn            The connection to use to communicate with the
963       *                         directory server.
964       * @param  dn              The DN of the entry to examine.
965       * @param  attributeNames  The names of the attributes expected to be present
966       *                         in the target entry.
967       *
968       * @return  A list containing the names of the attributes which were not
969       *          present in the target entry, an empty list if all specified
970       *          attributes were found in the entry, or {@code null} if the target
971       *          entry does not exist.
972       *
973       * @throws  LDAPException  If a problem is encountered while trying to
974       *                         communicate with the directory server.
975       */
976      public static List<String> getMissingAttributeNames(final LDAPInterface conn,
977                                      final String dn,
978                                      final Collection<String> attributeNames)
979             throws LDAPException
980      {
981        final List<String> missingAttrs =
982             new ArrayList<String>(attributeNames.size());
983    
984        // We will use a separate search for each target attribute so that we can
985        // handle the case in which the attribute is present with a different name
986        // than the one provided.
987        for (final String attrName : attributeNames)
988        {
989          try
990          {
991            final SearchResult result = conn.search(dn, SearchScope.BASE,
992                 Filter.createPresenceFilter(attrName));
993            if (result.getEntryCount() == 0)
994            {
995              missingAttrs.add(attrName);
996            }
997          }
998          catch (final LDAPException le)
999          {
1000            if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1001            {
1002              return null;
1003            }
1004            else
1005            {
1006              throw le;
1007            }
1008          }
1009        }
1010    
1011        return missingAttrs;
1012      }
1013    
1014    
1015    
1016      /**
1017       * Ensures that the specified entry exists in the directory with all of the
1018       * specified attributes.
1019       *
1020       * @param  conn            The connection to use to communicate with the
1021       *                         directory server.
1022       * @param  dn              The DN of the entry to examine.
1023       * @param  attributeNames  The names of the attributes that are expected to be
1024       *                         present in the provided entry.
1025       *
1026       * @throws  LDAPException  If a problem is encountered while trying to
1027       *                         communicate with the directory server.
1028       *
1029       * @throws  AssertionError  If the target entry does not exist or does not
1030       *                          contain all of the specified attributes.
1031       */
1032      public static void assertAttributeExists(final LDAPInterface conn,
1033                                               final String dn,
1034                                               final String... attributeNames)
1035            throws LDAPException, AssertionError
1036      {
1037        assertAttributeExists(conn, dn, StaticUtils.toList(attributeNames));
1038      }
1039    
1040    
1041    
1042      /**
1043       * Ensures that the specified entry exists in the directory with all of the
1044       * specified attributes.
1045       *
1046       * @param  conn            The connection to use to communicate with the
1047       *                         directory server.
1048       * @param  dn              The DN of the entry to examine.
1049       * @param  attributeNames  The names of the attributes that are expected to be
1050       *                         present in the provided entry.
1051       *
1052       * @throws  LDAPException  If a problem is encountered while trying to
1053       *                         communicate with the directory server.
1054       *
1055       * @throws  AssertionError  If the target entry does not exist or does not
1056       *                          contain all of the specified attributes.
1057       */
1058      public static void assertAttributeExists(final LDAPInterface conn,
1059                              final String dn,
1060                              final Collection<String> attributeNames)
1061            throws LDAPException, AssertionError
1062      {
1063        final List<String> missingAttrs =
1064             getMissingAttributeNames(conn, dn, attributeNames);
1065        if (missingAttrs == null)
1066        {
1067          // The target entry does not exist.
1068          throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1069        }
1070        else if (missingAttrs.isEmpty())
1071        {
1072          return;
1073        }
1074    
1075        final List<String> msgList = new ArrayList<String>(missingAttrs.size());
1076        for (final String attrName : missingAttrs)
1077        {
1078          msgList.add(ERR_TEST_ATTR_MISSING.get(dn, attrName));
1079        }
1080    
1081        throw new AssertionError(StaticUtils.concatenateStrings(msgList));
1082      }
1083    
1084    
1085    
1086      /**
1087       * Retrieves a list of all provided attribute values which are missing from
1088       * the specified entry.
1089       *
1090       * @param  conn             The connection to use to communicate with the
1091       *                          directory server.
1092       * @param  dn               The DN of the entry to examine.
1093       * @param  attributeName    The attribute expected to be present in the target
1094       *                          entry with the given values.
1095       * @param  attributeValues  The values expected to be present in the target
1096       *                          entry.
1097       *
1098       * @return  A list containing all of the provided values which were not found
1099       *          in the entry, an empty list if all provided attribute values were
1100       *          found, or {@code null} if the target entry does not exist.
1101       *
1102       * @throws  LDAPException  If a problem is encountered while trying to
1103       *                         communicate with the directory server.
1104       */
1105      public static List<String> getMissingAttributeValues(final LDAPInterface conn,
1106                                      final String dn, final String attributeName,
1107                                      final String... attributeValues)
1108             throws LDAPException
1109      {
1110        return getMissingAttributeValues(conn, dn, attributeName,
1111             StaticUtils.toList(attributeValues));
1112      }
1113    
1114    
1115    
1116      /**
1117       * Retrieves a list of all provided attribute values which are missing from
1118       * the specified entry.  The target attribute may or may not contain
1119       * additional values.
1120       *
1121       * @param  conn             The connection to use to communicate with the
1122       *                          directory server.
1123       * @param  dn               The DN of the entry to examine.
1124       * @param  attributeName    The attribute expected to be present in the target
1125       *                          entry with the given values.
1126       * @param  attributeValues  The values expected to be present in the target
1127       *                          entry.
1128       *
1129       * @return  A list containing all of the provided values which were not found
1130       *          in the entry, an empty list if all provided attribute values were
1131       *          found, or {@code null} if the target entry does not exist.
1132       *
1133       * @throws  LDAPException  If a problem is encountered while trying to
1134       *                         communicate with the directory server.
1135       */
1136      public static List<String> getMissingAttributeValues(final LDAPInterface conn,
1137                                      final String dn, final String attributeName,
1138                                      final Collection<String> attributeValues)
1139           throws LDAPException
1140      {
1141        final List<String> missingValues =
1142             new ArrayList<String>(attributeValues.size());
1143    
1144        for (final String value : attributeValues)
1145        {
1146          try
1147          {
1148            final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1149                 Filter.createEqualityFilter(attributeName, value), "1.1");
1150            if (searchResult.getEntryCount() == 0)
1151            {
1152              missingValues.add(value);
1153            }
1154          }
1155          catch (final LDAPException le)
1156          {
1157            if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1158            {
1159              return null;
1160            }
1161            else
1162            {
1163              throw le;
1164            }
1165          }
1166        }
1167    
1168        return missingValues;
1169      }
1170    
1171    
1172    
1173      /**
1174       * Ensures that the specified entry exists in the directory with all of the
1175       * specified values for the given attribute.  The attribute may or may not
1176       * contain additional values.
1177       *
1178       * @param  conn             The connection to use to communicate with the
1179       *                          directory server.
1180       * @param  dn               The DN of the entry to examine.
1181       * @param  attributeName    The name of the attribute to examine.
1182       * @param  attributeValues  The set of values which must exist for the given
1183       *                          attribute.
1184       *
1185       * @throws  LDAPException  If a problem is encountered while trying to
1186       *                         communicate with the directory server.
1187       *
1188       * @throws  AssertionError  If the target entry does not exist, does not
1189       *                          contain the specified attribute, or that attribute
1190       *                          does not have all of the specified values.
1191       */
1192      public static void assertValueExists(final LDAPInterface conn,
1193                                           final String dn,
1194                                           final String attributeName,
1195                                           final String... attributeValues)
1196            throws LDAPException, AssertionError
1197      {
1198        assertValueExists(conn, dn, attributeName,
1199             StaticUtils.toList(attributeValues));
1200      }
1201    
1202    
1203    
1204      /**
1205       * Ensures that the specified entry exists in the directory with all of the
1206       * specified values for the given attribute.  The attribute may or may not
1207       * contain additional values.
1208       *
1209       * @param  conn             The connection to use to communicate with the
1210       *                          directory server.
1211       * @param  dn               The DN of the entry to examine.
1212       * @param  attributeName    The name of the attribute to examine.
1213       * @param  attributeValues  The set of values which must exist for the given
1214       *                          attribute.
1215       *
1216       * @throws  LDAPException  If a problem is encountered while trying to
1217       *                         communicate with the directory server.
1218       *
1219       * @throws  AssertionError  If the target entry does not exist, does not
1220       *                          contain the specified attribute, or that attribute
1221       *                          does not have all of the specified values.
1222       */
1223      public static void assertValueExists(final LDAPInterface conn,
1224                                           final String dn,
1225                                           final String attributeName,
1226                                           final Collection<String> attributeValues)
1227            throws LDAPException, AssertionError
1228      {
1229        final List<String> missingValues =
1230             getMissingAttributeValues(conn, dn, attributeName, attributeValues);
1231        if (missingValues == null)
1232        {
1233          // The target entry does not exist.
1234          throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1235        }
1236        else if (missingValues.isEmpty())
1237        {
1238          return;
1239        }
1240    
1241        // Get the entry and see if the attribute exists in it at all.
1242        final Entry entry = conn.getEntry(dn, attributeName);
1243        if ((entry != null) && entry.hasAttribute(attributeName))
1244        {
1245          final Attribute a = entry.getAttribute(attributeName);
1246          throw new AssertionError(ERR_TEST_ATTR_MISSING_VALUE.get(dn,
1247               attributeName,
1248               StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1249                    a.getValues()),
1250               StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1251                    missingValues)));
1252        }
1253        else
1254        {
1255          throw new AssertionError(ERR_TEST_ATTR_MISSING.get(dn, attributeName));
1256        }
1257      }
1258    
1259    
1260    
1261      /**
1262       * Ensures that the specified entry does not exist in the directory.
1263       *
1264       * @param  conn  The connection to use to communicate with the directory
1265       *               server.
1266       * @param  dn    The DN of the entry expected to be missing.
1267       *
1268       * @throws  LDAPException  If a problem is encountered while trying to
1269       *                         communicate with the directory server.
1270       *
1271       * @throws  AssertionError  If the target entry is found in the server.
1272       */
1273      public static void assertEntryMissing(final LDAPInterface conn,
1274                                            final String dn)
1275             throws LDAPException, AssertionError
1276      {
1277        if (conn.getEntry(dn, "1.1") != null)
1278        {
1279          throw new AssertionError(ERR_TEST_ENTRY_EXISTS.get(dn));
1280        }
1281      }
1282    
1283    
1284    
1285      /**
1286       * Ensures that the specified entry exists in the directory but does not
1287       * contain any of the specified attributes.
1288       *
1289       * @param  conn            The connection to use to communicate with the
1290       *                         directory server.
1291       * @param  dn              The DN of the entry expected to be present.
1292       * @param  attributeNames  The names of the attributes expected to be missing
1293       *                         from the entry.
1294       *
1295       * @throws  LDAPException  If a problem is encountered while trying to
1296       *                         communicate with the directory server.
1297       *
1298       * @throws  AssertionError  If the target entry is missing from the server, or
1299       *                          if it contains any of the target attributes.
1300       */
1301      public static void assertAttributeMissing(final LDAPInterface conn,
1302                                                final String dn,
1303                                                final String... attributeNames)
1304             throws LDAPException, AssertionError
1305      {
1306        assertAttributeMissing(conn, dn, StaticUtils.toList(attributeNames));
1307      }
1308    
1309    
1310    
1311      /**
1312       * Ensures that the specified entry exists in the directory but does not
1313       * contain any of the specified attributes.
1314       *
1315       * @param  conn            The connection to use to communicate with the
1316       *                         directory server.
1317       * @param  dn              The DN of the entry expected to be present.
1318       * @param  attributeNames  The names of the attributes expected to be missing
1319       *                         from the entry.
1320       *
1321       * @throws  LDAPException  If a problem is encountered while trying to
1322       *                         communicate with the directory server.
1323       *
1324       * @throws  AssertionError  If the target entry is missing from the server, or
1325       *                          if it contains any of the target attributes.
1326       */
1327      public static void assertAttributeMissing(final LDAPInterface conn,
1328                              final String dn,
1329                              final Collection<String> attributeNames)
1330             throws LDAPException, AssertionError
1331      {
1332        final List<String> messages = new ArrayList<String>(attributeNames.size());
1333        for (final String attrName : attributeNames)
1334        {
1335          try
1336          {
1337            final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1338                 Filter.createPresenceFilter(attrName), attrName);
1339            if (searchResult.getEntryCount() == 1)
1340            {
1341              final Attribute a =
1342                   searchResult.getSearchEntries().get(0).getAttribute(attrName);
1343              if (a == null)
1344              {
1345                messages.add(ERR_TEST_ATTR_EXISTS.get(dn, attrName));
1346              }
1347              else
1348              {
1349                messages.add(ERR_TEST_ATTR_EXISTS_WITH_VALUES.get(dn, attrName,
1350                     StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1351                                     a.getValues())));
1352              }
1353            }
1354          }
1355          catch (final LDAPException le)
1356          {
1357            if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1358            {
1359              throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1360            }
1361            else
1362            {
1363              throw le;
1364            }
1365          }
1366        }
1367    
1368        if (! messages.isEmpty())
1369        {
1370          throw new AssertionError(StaticUtils.concatenateStrings(messages));
1371        }
1372      }
1373    
1374    
1375    
1376      /**
1377       * Ensures that the specified entry exists in the directory but does not
1378       * contain any of the specified attribute values.
1379       *
1380       * @param  conn             The connection to use to communicate with the
1381       *                          directory server.
1382       * @param  dn               The DN of the entry expected to be present.
1383       * @param  attributeName    The name of the attribute to examine.
1384       * @param  attributeValues  The values expected to be missing from the target
1385       *                          entry.
1386       *
1387       * @throws  LDAPException  If a problem is encountered while trying to
1388       *                         communicate with the directory server.
1389       *
1390       * @throws  AssertionError  If the target entry is missing from the server, or
1391       *                          if it contains any of the target attribute values.
1392       */
1393      public static void assertValueMissing(final LDAPInterface conn,
1394                              final String dn, final String attributeName,
1395                              final String... attributeValues)
1396             throws LDAPException, AssertionError
1397      {
1398        assertValueMissing(conn, dn, attributeName,
1399             StaticUtils.toList(attributeValues));
1400      }
1401    
1402    
1403    
1404      /**
1405       * Ensures that the specified entry exists in the directory but does not
1406       * contain any of the specified attribute values.
1407       *
1408       * @param  conn             The connection to use to communicate with the
1409       *                          directory server.
1410       * @param  dn               The DN of the entry expected to be present.
1411       * @param  attributeName    The name of the attribute to examine.
1412       * @param  attributeValues  The values expected to be missing from the target
1413       *                          entry.
1414       *
1415       * @throws  LDAPException  If a problem is encountered while trying to
1416       *                         communicate with the directory server.
1417       *
1418       * @throws  AssertionError  If the target entry is missing from the server, or
1419       *                          if it contains any of the target attribute values.
1420       */
1421      public static void assertValueMissing(final LDAPInterface conn,
1422                              final String dn, final String attributeName,
1423                              final Collection<String> attributeValues)
1424             throws LDAPException, AssertionError
1425      {
1426        final List<String> messages = new ArrayList<String>(attributeValues.size());
1427        for (final String value : attributeValues)
1428        {
1429          try
1430          {
1431            final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1432                 Filter.createEqualityFilter(attributeName, value), "1.1");
1433            if (searchResult.getEntryCount() == 1)
1434            {
1435              messages.add(ERR_TEST_VALUE_EXISTS.get(dn, attributeName, value));
1436            }
1437          }
1438          catch (final LDAPException le)
1439          {
1440            if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1441            {
1442              throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1443            }
1444            else
1445            {
1446              throw le;
1447            }
1448          }
1449        }
1450    
1451        if (! messages.isEmpty())
1452        {
1453          throw new AssertionError(StaticUtils.concatenateStrings(messages));
1454        }
1455      }
1456    
1457    
1458    
1459      /**
1460       * Ensures that the result code for the provided result matches one of the
1461       * given acceptable result codes.
1462       *
1463       * @param  result                 The LDAP result to examine.
1464       * @param  acceptableResultCodes  The set of result codes that are considered
1465       *                                acceptable.
1466       *
1467       * @throws  AssertionError  If the result code from the provided result did
1468       *                          not match any of the acceptable values.
1469       */
1470      public static void assertResultCodeEquals(final LDAPResult result,
1471                              final ResultCode... acceptableResultCodes)
1472             throws AssertionError
1473      {
1474        for (final ResultCode rc : acceptableResultCodes)
1475        {
1476          if (rc.equals(result.getResultCode()))
1477          {
1478            return;
1479          }
1480        }
1481    
1482        if (acceptableResultCodes.length == 1)
1483        {
1484          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1485               String.valueOf(result), String.valueOf(acceptableResultCodes[0])));
1486        }
1487        else
1488        {
1489          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1490               String.valueOf(result), Arrays.toString(acceptableResultCodes)));
1491        }
1492      }
1493    
1494    
1495    
1496      /**
1497       * Ensures that the result code for the provided LDAP exception matches one of
1498       * the given acceptable result codes.
1499       *
1500       * @param  exception              The LDAP exception to examine.
1501       * @param  acceptableResultCodes  The set of result codes that are considered
1502       *                                acceptable.
1503       *
1504       * @throws  AssertionError  If the result code from the provided exception did
1505       *                          not match any of the acceptable values.
1506       */
1507      public static void assertResultCodeEquals(final LDAPException exception,
1508                              final ResultCode... acceptableResultCodes)
1509             throws AssertionError
1510      {
1511        for (final ResultCode rc : acceptableResultCodes)
1512        {
1513          if (rc.equals(exception.getResultCode()))
1514          {
1515            return;
1516          }
1517        }
1518    
1519        if (acceptableResultCodes.length == 1)
1520        {
1521          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1522               StaticUtils.getExceptionMessage(exception),
1523               String.valueOf(acceptableResultCodes[0])));
1524        }
1525        else
1526        {
1527          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1528               StaticUtils.getExceptionMessage(exception),
1529               Arrays.toString(acceptableResultCodes)));
1530        }
1531      }
1532    
1533    
1534    
1535      /**
1536       * Processes the provided request using the given connection and ensures that
1537       * the result code matches one of the provided acceptable values.
1538       *
1539       * @param  conn                   The connection to use to communicate with
1540       *                                the directory server.
1541       * @param  request                The request to be processed.
1542       * @param  acceptableResultCodes  The set of result codes that are considered
1543       *                                acceptable.
1544       *
1545       * @return  The result returned from processing the requested operation.
1546       *
1547       * @throws  AssertionError  If the result code returned by the server did not
1548       *                          match any acceptable values.
1549       */
1550      public static LDAPResult assertResultCodeEquals(final LDAPConnection conn,
1551                                    final LDAPRequest request,
1552                                    final ResultCode... acceptableResultCodes)
1553             throws AssertionError
1554      {
1555        LDAPResult result;
1556    
1557        try
1558        {
1559          result = conn.processOperation(request);
1560        }
1561        catch (final LDAPException le)
1562        {
1563          result = le.toLDAPResult();
1564        }
1565    
1566        for (final ResultCode rc : acceptableResultCodes)
1567        {
1568          if (rc.equals(result.getResultCode()))
1569          {
1570            return result;
1571          }
1572        }
1573    
1574        if (acceptableResultCodes.length == 1)
1575        {
1576          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1577               String.valueOf(result), String.valueOf(acceptableResultCodes[0])));
1578        }
1579        else
1580        {
1581          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1582               String.valueOf(result), Arrays.toString(acceptableResultCodes)));
1583        }
1584      }
1585    
1586    
1587    
1588      /**
1589       * Ensures that the result code for the provided result does not match any of
1590       * the given unacceptable result codes.
1591       *
1592       * @param  result                   The LDAP result to examine.
1593       * @param  unacceptableResultCodes  The set of result codes that are
1594       *                                  considered unacceptable.
1595       *
1596       * @throws  AssertionError  If the result code from the provided result
1597       *                          matched any of the unacceptable values.
1598       */
1599      public static void assertResultCodeNot(final LDAPResult result,
1600                              final ResultCode... unacceptableResultCodes)
1601             throws AssertionError
1602      {
1603        for (final ResultCode rc : unacceptableResultCodes)
1604        {
1605          if (rc.equals(result.getResultCode()))
1606          {
1607            if (unacceptableResultCodes.length == 1)
1608            {
1609              throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1610                   String.valueOf(result),
1611                   String.valueOf(unacceptableResultCodes[0])));
1612            }
1613            else
1614            {
1615              throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1616                   String.valueOf(result),
1617                   Arrays.toString(unacceptableResultCodes)));
1618            }
1619          }
1620        }
1621      }
1622    
1623    
1624    
1625      /**
1626       * Ensures that the result code for the provided result does not match any of
1627       * the given unacceptable result codes.
1628       *
1629       * @param  exception                The LDAP exception to examine.
1630       * @param  unacceptableResultCodes  The set of result codes that are
1631       *                                  considered unacceptable.
1632       *
1633       * @throws  AssertionError  If the result code from the provided result
1634       *                          matched any of the unacceptable values.
1635       */
1636      public static void assertResultCodeNot(final LDAPException exception,
1637                              final ResultCode... unacceptableResultCodes)
1638             throws AssertionError
1639      {
1640        for (final ResultCode rc : unacceptableResultCodes)
1641        {
1642          if (rc.equals(exception.getResultCode()))
1643          {
1644            if (unacceptableResultCodes.length == 1)
1645            {
1646              throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1647                   StaticUtils.getExceptionMessage(exception),
1648                   String.valueOf(unacceptableResultCodes[0])));
1649            }
1650            else
1651            {
1652              throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1653                   StaticUtils.getExceptionMessage(exception),
1654                   Arrays.toString(unacceptableResultCodes)));
1655            }
1656          }
1657        }
1658      }
1659    
1660    
1661    
1662      /**
1663       * Processes the provided request using the given connection and ensures that
1664       * the result code does not match any of the given unacceptable values.
1665       *
1666       * @param  conn                     The connection to use to communicate with
1667       *                                  the directory server.
1668       * @param  request                  The request to be processed.
1669       * @param  unacceptableResultCodes  The set of result codes that are
1670       *                                  considered unacceptable.
1671       *
1672       * @return  The result returned from processing the requested operation.
1673       *
1674       * @throws  AssertionError  If the result code from the provided result
1675       *                          matched any of the unacceptable values.
1676       */
1677      public static LDAPResult assertResultCodeNot(final LDAPConnection conn,
1678                                    final LDAPRequest request,
1679                                    final ResultCode... unacceptableResultCodes)
1680             throws AssertionError
1681      {
1682        LDAPResult result;
1683    
1684        try
1685        {
1686          result = conn.processOperation(request);
1687        }
1688        catch (final LDAPException le)
1689        {
1690          result = le.toLDAPResult();
1691        }
1692    
1693        for (final ResultCode rc : unacceptableResultCodes)
1694        {
1695          if (rc.equals(result.getResultCode()))
1696          {
1697            if (unacceptableResultCodes.length == 1)
1698            {
1699              throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1700                   String.valueOf(result),
1701                   String.valueOf(unacceptableResultCodes[0])));
1702            }
1703            else
1704            {
1705              throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1706                   String.valueOf(result),
1707                   Arrays.toString(unacceptableResultCodes)));
1708            }
1709          }
1710        }
1711    
1712        return result;
1713      }
1714    
1715    
1716    
1717      /**
1718       * Ensures that the provided LDAP result contains a matched DN value.
1719       *
1720       * @param  result  The LDAP result to examine.
1721       *
1722       * @throws  AssertionError  If the provided result did not contain a matched
1723       *                          DN value.
1724       */
1725      public static void assertContainsMatchedDN(final LDAPResult result)
1726             throws AssertionError
1727      {
1728        if (result.getMatchedDN() == null)
1729        {
1730          throw new AssertionError(ERR_TEST_RESULT_MISSING_MATCHED_DN.get(
1731               String.valueOf(result)));
1732        }
1733      }
1734    
1735    
1736    
1737      /**
1738       * Ensures that the provided LDAP exception contains a matched DN value.
1739       *
1740       * @param  exception  The LDAP exception to examine.
1741       *
1742       * @throws  AssertionError  If the provided exception did not contain a
1743       *                          matched DN value.
1744       */
1745      public static void assertContainsMatchedDN(final LDAPException exception)
1746             throws AssertionError
1747      {
1748        if (exception.getMatchedDN() == null)
1749        {
1750          throw new AssertionError(ERR_TEST_RESULT_MISSING_MATCHED_DN.get(
1751               StaticUtils.getExceptionMessage(exception)));
1752        }
1753      }
1754    
1755    
1756    
1757      /**
1758       * Ensures that the provided LDAP result does not contain a matched DN value.
1759       *
1760       * @param  result  The LDAP result to examine.
1761       *
1762       * @throws  AssertionError  If the provided result contained a matched DN
1763       *                          value.
1764       */
1765      public static void assertMissingMatchedDN(final LDAPResult result)
1766             throws AssertionError
1767      {
1768        if (result.getMatchedDN() != null)
1769        {
1770          throw new AssertionError(ERR_TEST_RESULT_CONTAINS_MATCHED_DN.get(
1771               String.valueOf(result), result.getMatchedDN()));
1772        }
1773      }
1774    
1775    
1776    
1777      /**
1778       * Ensures that the provided LDAP exception does not contain a matched DN
1779       * value.
1780       *
1781       * @param  exception  The LDAP exception to examine.
1782       *
1783       * @throws  AssertionError  If the provided exception contained a matched DN
1784       *                          value.
1785       */
1786      public static void assertMissingMatchedDN(final LDAPException exception)
1787             throws AssertionError
1788      {
1789        if (exception.getMatchedDN() != null)
1790        {
1791          throw new AssertionError(ERR_TEST_RESULT_CONTAINS_MATCHED_DN.get(
1792               StaticUtils.getExceptionMessage(exception),
1793               exception.getMatchedDN()));
1794        }
1795      }
1796    
1797    
1798    
1799      /**
1800       * Ensures that the provided LDAP result has the given matched DN value.
1801       *
1802       * @param  result     The LDAP result to examine.
1803       * @param  matchedDN  The matched DN value expected to be found in the
1804       *                    provided result.  It must not be {@code null}.
1805       *
1806       * @throws  LDAPException  If either the found or expected matched DN values
1807       *                         could not be parsed as a valid DN.
1808       *
1809       * @throws  AssertionError  If the provided LDAP result did not contain a
1810       *                          matched DN, or if it had a matched DN that
1811       *                          differed from the expected value.
1812       */
1813      public static void assertMatchedDNEquals(final LDAPResult result,
1814                                               final String matchedDN)
1815             throws LDAPException, AssertionError
1816      {
1817        if (result.getMatchedDN() == null)
1818        {
1819          throw new AssertionError(ERR_TEST_RESULT_MISSING_EXPECTED_MATCHED_DN.get(
1820               String.valueOf(result), matchedDN));
1821        }
1822    
1823        final DN foundDN    = new DN(result.getMatchedDN());
1824        final DN expectedDN = new DN(matchedDN);
1825        if (! foundDN.equals(expectedDN))
1826        {
1827          throw new AssertionError(ERR_TEST_MATCHED_DN_MISMATCH.get(
1828               String.valueOf(result), matchedDN, result.getMatchedDN()));
1829        }
1830      }
1831    
1832    
1833    
1834      /**
1835       * Ensures that the provided LDAP exception has the given matched DN value.
1836       *
1837       * @param  exception  The LDAP exception to examine.
1838       * @param  matchedDN  The matched DN value expected to be found in the
1839       *                    provided exception.  It must not be {@code null}.
1840       *
1841       * @throws  LDAPException  If either the found or expected matched DN values
1842       *                         could not be parsed as a valid DN.
1843       *
1844       * @throws  AssertionError  If the provided LDAP exception did not contain a
1845       *                          matched DN, or if it had a matched DN that
1846       *                          differed from the expected value.
1847       */
1848      public static void assertMatchedDNEquals(final LDAPException exception,
1849                                               final String matchedDN)
1850             throws LDAPException, AssertionError
1851      {
1852        if (exception.getMatchedDN() == null)
1853        {
1854          throw new AssertionError(ERR_TEST_RESULT_MISSING_EXPECTED_MATCHED_DN.get(
1855               StaticUtils.getExceptionMessage(exception), matchedDN));
1856        }
1857    
1858        final DN foundDN    = new DN(exception.getMatchedDN());
1859        final DN expectedDN = new DN(matchedDN);
1860        if (! foundDN.equals(expectedDN))
1861        {
1862          throw new AssertionError(ERR_TEST_MATCHED_DN_MISMATCH.get(
1863               StaticUtils.getExceptionMessage(exception), matchedDN,
1864               exception.getMatchedDN()));
1865        }
1866      }
1867    
1868    
1869    
1870      /**
1871       * Ensures that the provided LDAP result has one or more referral URLs.
1872       *
1873       * @param  result  The LDAP result to examine.
1874       *
1875       * @throws  AssertionError  If the provided result does not have any referral
1876       *                          URLs.
1877       */
1878      public static void assertHasReferral(final LDAPResult result)
1879             throws AssertionError
1880      {
1881        final String[] referralURLs = result.getReferralURLs();
1882        if ((referralURLs == null) || (referralURLs.length == 0))
1883        {
1884          throw new AssertionError(ERR_TEST_RESULT_MISSING_REFERRAL.get(
1885               String.valueOf(result)));
1886        }
1887      }
1888    
1889    
1890    
1891      /**
1892       * Ensures that the provided LDAP exception has one or more referral URLs.
1893       *
1894       * @param  exception  The LDAP exception to examine.
1895       *
1896       * @throws  AssertionError  If the provided exception does not have any
1897       *                          referral URLs.
1898       */
1899      public static void assertHasReferral(final LDAPException exception)
1900             throws AssertionError
1901      {
1902        final String[] referralURLs = exception.getReferralURLs();
1903        if ((referralURLs == null) || (referralURLs.length == 0))
1904        {
1905          throw new AssertionError(ERR_TEST_RESULT_MISSING_REFERRAL.get(
1906               StaticUtils.getExceptionMessage(exception)));
1907        }
1908      }
1909    
1910    
1911    
1912      /**
1913       * Ensures that the provided LDAP result does not have any referral URLs.
1914       *
1915       * @param  result  The LDAP result to examine.
1916       *
1917       * @throws  AssertionError  If the provided result has one or more referral
1918       *                          URLs.
1919       */
1920      public static void assertMissingReferral(final LDAPResult result)
1921             throws AssertionError
1922      {
1923        final String[] referralURLs = result.getReferralURLs();
1924        if ((referralURLs != null) && (referralURLs.length > 0))
1925        {
1926          throw new AssertionError(ERR_TEST_RESULT_HAS_REFERRAL.get(
1927               String.valueOf(result)));
1928        }
1929      }
1930    
1931    
1932    
1933      /**
1934       * Ensures that the provided LDAP exception does not have any referral URLs.
1935       *
1936       * @param  exception  The LDAP exception to examine.
1937       *
1938       * @throws  AssertionError  If the provided exception has one or more referral
1939       *                          URLs.
1940       */
1941      public static void assertMissingReferral(final LDAPException exception)
1942             throws AssertionError
1943      {
1944        final String[] referralURLs = exception.getReferralURLs();
1945        if ((referralURLs != null) && (referralURLs.length > 0))
1946        {
1947          throw new AssertionError(ERR_TEST_RESULT_HAS_REFERRAL.get(
1948               StaticUtils.getExceptionMessage(exception)));
1949        }
1950      }
1951    
1952    
1953    
1954      /**
1955       * Ensures that the provided LDAP result includes at least one control with
1956       * the specified OID.
1957       *
1958       * @param  result  The LDAP result to examine.
1959       * @param  oid     The OID of the control which is expected to be present in
1960       *                 the result.
1961       *
1962       * @return  The first control found with the specified OID.
1963       *
1964       * @throws  AssertionError  If the provided LDAP result does not include any
1965       *                          control with the specified OID.
1966       */
1967      public static Control assertHasControl(final LDAPResult result,
1968                                             final String oid)
1969             throws AssertionError
1970      {
1971        for (final Control c : result.getResponseControls())
1972        {
1973          if (c.getOID().equals(oid))
1974          {
1975            return c;
1976          }
1977        }
1978    
1979        throw new AssertionError(ERR_TEST_RESULT_MISSING_CONTROL.get(
1980             String.valueOf(result), oid));
1981      }
1982    
1983    
1984    
1985      /**
1986       * Ensures that the provided LDAP exception includes at least one control with
1987       * the specified OID.
1988       *
1989       * @param  exception  The LDAP exception to examine.
1990       * @param  oid        The OID of the control which is expected to be present
1991       *                    in the exception.
1992       *
1993       * @return  The first control found with the specified OID.
1994       *
1995       * @throws  AssertionError  If the provided LDAP exception does not include
1996       *                          any control with the specified OID.
1997       */
1998      public static Control assertHasControl(final LDAPException exception,
1999                                             final String oid)
2000             throws AssertionError
2001      {
2002        for (final Control c : exception.getResponseControls())
2003        {
2004          if (c.getOID().equals(oid))
2005          {
2006            return c;
2007          }
2008        }
2009    
2010        throw new AssertionError(ERR_TEST_RESULT_MISSING_CONTROL.get(
2011             StaticUtils.getExceptionMessage(exception), oid));
2012      }
2013    
2014    
2015    
2016      /**
2017       * Ensures that the provided search result entry includes at least one control
2018       * with the specified OID.
2019       *
2020       * @param  entry  The search result entry to examine.
2021       * @param  oid    The OID of the control which is expected to be present in
2022       *                the search result entry.
2023       *
2024       * @return  The first control found with the specified OID.
2025       *
2026       * @throws  AssertionError  If the provided search result entry does not
2027       *                          include any control with the specified OID.
2028       */
2029      public static Control assertHasControl(final SearchResultEntry entry,
2030                                             final String oid)
2031             throws AssertionError
2032      {
2033        for (final Control c : entry.getControls())
2034        {
2035          if (c.getOID().equals(oid))
2036          {
2037            return c;
2038          }
2039        }
2040    
2041        throw new AssertionError(ERR_TEST_ENTRY_MISSING_CONTROL.get(
2042             String.valueOf(entry), oid));
2043      }
2044    
2045    
2046    
2047      /**
2048       * Ensures that the provided search result reference includes at least one
2049       * control with the specified OID.
2050       *
2051       * @param  reference  The search result reference to examine.
2052       * @param  oid        The OID of the control which is expected to be present
2053       *                    in the search result reference.
2054       *
2055       * @return  The first control found with the specified OID.
2056       *
2057       * @throws  AssertionError  If the provided search result reference does not
2058       *                          include any control with the specified OID.
2059       */
2060      public static Control assertHasControl(final SearchResultReference reference,
2061                                             final String oid)
2062             throws AssertionError
2063      {
2064        for (final Control c : reference.getControls())
2065        {
2066          if (c.getOID().equals(oid))
2067          {
2068            return c;
2069          }
2070        }
2071    
2072        throw new AssertionError(ERR_TEST_REF_MISSING_CONTROL.get(
2073             String.valueOf(reference), oid));
2074      }
2075    
2076    
2077    
2078      /**
2079       * Ensures that the provided LDAP result does not include any control with
2080       * the specified OID.
2081       *
2082       * @param  result  The LDAP result to examine.
2083       * @param  oid     The OID of the control which is not expected to be present
2084       *                 in the result.
2085       *
2086       * @throws  AssertionError  If the provided LDAP result includes any control
2087       *                          with the specified OID.
2088       */
2089      public static void assertMissingControl(final LDAPResult result,
2090                                              final String oid)
2091             throws AssertionError
2092      {
2093        for (final Control c : result.getResponseControls())
2094        {
2095          if (c.getOID().equals(oid))
2096          {
2097            throw new AssertionError(ERR_TEST_RESULT_HAS_CONTROL.get(
2098                 String.valueOf(result), oid));
2099          }
2100        }
2101      }
2102    
2103    
2104    
2105      /**
2106       * Ensures that the provided LDAP exception does not include any control with
2107       * the specified OID.
2108       *
2109       * @param  exception  The LDAP exception to examine.
2110       * @param  oid        The OID of the control which is not expected to be
2111       *                    present in the exception.
2112       *
2113       * @throws  AssertionError  If the provided LDAP exception includes any
2114       *                          control with the specified OID.
2115       */
2116      public static void assertMissingControl(final LDAPException exception,
2117                                              final String oid)
2118             throws AssertionError
2119      {
2120        for (final Control c : exception.getResponseControls())
2121        {
2122          if (c.getOID().equals(oid))
2123          {
2124            throw new AssertionError(ERR_TEST_RESULT_HAS_CONTROL.get(
2125                 StaticUtils.getExceptionMessage(exception), oid));
2126          }
2127        }
2128      }
2129    
2130    
2131    
2132      /**
2133       * Ensures that the provided search result entry does not includes any control
2134       * with the specified OID.
2135       *
2136       * @param  entry  The search result entry to examine.
2137       * @param  oid    The OID of the control which is not expected to be present
2138       *                in the search result entry.
2139       *
2140       * @throws  AssertionError  If the provided search result entry includes any
2141       *                          control with the specified OID.
2142       */
2143      public static void assertMissingControl(final SearchResultEntry entry,
2144                                              final String oid)
2145             throws AssertionError
2146      {
2147        for (final Control c : entry.getControls())
2148        {
2149          if (c.getOID().equals(oid))
2150          {
2151            throw new AssertionError(ERR_TEST_ENTRY_HAS_CONTROL.get(
2152                 String.valueOf(entry), oid));
2153          }
2154        }
2155      }
2156    
2157    
2158    
2159      /**
2160       * Ensures that the provided search result reference does not includes any
2161       * control with the specified OID.
2162       *
2163       * @param  reference  The search result reference to examine.
2164       * @param  oid        The OID of the control which is not expected to be
2165       *                    present in the search result reference.
2166       *
2167       * @throws  AssertionError  If the provided search result reference includes
2168       *                          any control with the specified OID.
2169       */
2170      public static void assertMissingControl(final SearchResultReference reference,
2171                                              final String oid)
2172             throws AssertionError
2173      {
2174        for (final Control c : reference.getControls())
2175        {
2176          if (c.getOID().equals(oid))
2177          {
2178            throw new AssertionError(ERR_TEST_REF_HAS_CONTROL.get(
2179                 String.valueOf(reference), oid));
2180          }
2181        }
2182      }
2183    
2184    
2185    
2186      /**
2187       * Ensures that the provided search result indicates that at least one search
2188       * result entry was returned.
2189       *
2190       * @param  result  The search result to examine.
2191       *
2192       * @return  The number of search result entries that were returned.
2193       *
2194       * @throws  AssertionError  If the provided search result indicates that no
2195       *                          entries were returned.
2196       */
2197      public static int assertEntryReturned(final SearchResult result)
2198             throws AssertionError
2199      {
2200        if (result.getEntryCount() == 0)
2201        {
2202          throw new AssertionError(ERR_TEST_SEARCH_NO_ENTRIES_RETURNED.get(
2203               String.valueOf(result)));
2204        }
2205    
2206        return result.getEntryCount();
2207      }
2208    
2209    
2210    
2211      /**
2212       * Ensures that the provided search exception indicates that at least one
2213       * search result entry was returned.
2214       *
2215       * @param  exception  The search exception to examine.
2216       *
2217       * @return  The number of search result entries that were returned.
2218       *
2219       * @throws  AssertionError  If the provided search exception indicates that no
2220       *                          entries were returned.
2221       */
2222      public static int assertEntryReturned(final LDAPSearchException exception)
2223             throws AssertionError
2224      {
2225        if (exception.getEntryCount() == 0)
2226        {
2227          throw new AssertionError(ERR_TEST_SEARCH_NO_ENTRIES_RETURNED.get(
2228               StaticUtils.getExceptionMessage(exception)));
2229        }
2230    
2231        return exception.getEntryCount();
2232      }
2233    
2234    
2235    
2236      /**
2237       * Ensures that the specified search result entry was included in provided
2238       * search result.
2239       *
2240       * @param  result  The search result to examine.
2241       * @param  dn      The DN of the entry expected to be included in the
2242       *                 search result.
2243       *
2244       * @return  The search result entry with the provided DN.
2245       *
2246       * @throws  LDAPException  If the provided string cannot be parsed as a valid
2247       *                         DN.
2248       *
2249       * @throws  AssertionError  If the specified entry was not included in the
2250       *                          set of entries that were returned, or if a search
2251       *                          result listener was used which makes the
2252       *                          determination impossible.
2253       */
2254      public static SearchResultEntry assertEntryReturned(final SearchResult result,
2255                                                          final String dn)
2256             throws LDAPException, AssertionError
2257      {
2258        final DN parsedDN = new DN(dn);
2259    
2260        final List<SearchResultEntry> entryList = result.getSearchEntries();
2261        if (entryList != null)
2262        {
2263          for (final SearchResultEntry e : entryList)
2264          {
2265            if (e.getParsedDN().equals(parsedDN))
2266            {
2267              return e;
2268            }
2269          }
2270        }
2271    
2272        throw new AssertionError(ERR_TEST_SEARCH_ENTRY_NOT_RETURNED.get(
2273             String.valueOf(result), dn));
2274      }
2275    
2276    
2277    
2278      /**
2279       * Ensures that the specified search result entry was included in provided
2280       * search exception.
2281       *
2282       * @param  exception  The search exception to examine.
2283       * @param  dn         The DN of the entry expected to be included in the
2284       *                    search exception.
2285       *
2286       * @return  The search result entry with the provided DN.
2287       *
2288       * @throws  LDAPException  If the provided string cannot be parsed as a valid
2289       *                         DN.
2290       *
2291       * @throws  AssertionError  If the specified entry was not included in the
2292       *                          set of entries that were returned, or if a search
2293       *                          result listener was used which makes the
2294       *                          determination impossible.
2295       */
2296      public static SearchResultEntry assertEntryReturned(
2297                                           final LDAPSearchException exception,
2298                                           final String dn)
2299             throws LDAPException, AssertionError
2300      {
2301        final DN parsedDN = new DN(dn);
2302    
2303        final List<SearchResultEntry> entryList = exception.getSearchEntries();
2304        if (entryList != null)
2305        {
2306          for (final SearchResultEntry e : entryList)
2307          {
2308            if (e.getParsedDN().equals(parsedDN))
2309            {
2310              return e;
2311            }
2312          }
2313        }
2314    
2315        throw new AssertionError(ERR_TEST_SEARCH_ENTRY_NOT_RETURNED.get(
2316             StaticUtils.getExceptionMessage(exception), dn));
2317      }
2318    
2319    
2320    
2321      /**
2322       * Ensures that the provided search result indicates that no search result
2323       * entries were returned.
2324       *
2325       * @param  result  The search result to examine.
2326       *
2327       * @throws  AssertionError  If the provided search result indicates that one
2328       *                          or more entries were returned.
2329       */
2330      public static void assertNoEntriesReturned(final SearchResult result)
2331             throws AssertionError
2332      {
2333        if (result.getEntryCount() > 0)
2334        {
2335          throw new AssertionError(ERR_TEST_SEARCH_ENTRIES_RETURNED.get(
2336               String.valueOf(result), result.getEntryCount()));
2337        }
2338      }
2339    
2340    
2341    
2342      /**
2343       * Ensures that the provided search exception indicates that no search result
2344       * entries were returned.
2345       *
2346       * @param  exception  The search exception to examine.
2347       *
2348       * @throws  AssertionError  If the provided search exception indicates that
2349       *                          one or more entries were returned.
2350       */
2351      public static void assertNoEntriesReturned(
2352                              final LDAPSearchException exception)
2353             throws AssertionError
2354      {
2355        if (exception.getEntryCount() > 0)
2356        {
2357          throw new AssertionError(ERR_TEST_SEARCH_ENTRIES_RETURNED.get(
2358               StaticUtils.getExceptionMessage(exception),
2359               exception.getEntryCount()));
2360        }
2361      }
2362    
2363    
2364    
2365      /**
2366       * Ensures that the provided search result indicates that the expected number
2367       * of entries were returned.
2368       *
2369       * @param  result              The search result to examine.
2370       * @param  expectedEntryCount  The number of expected search result entries.
2371       *
2372       * @throws  AssertionError  If the number of entries returned does not match
2373       *                          the expected value.
2374       */
2375      public static void assertEntriesReturnedEquals(final SearchResult result,
2376                                                     final int expectedEntryCount)
2377             throws AssertionError
2378      {
2379        if (result.getEntryCount() != expectedEntryCount)
2380        {
2381          if (expectedEntryCount == 1)
2382          {
2383            throw new AssertionError(
2384                 ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_ONE_EXPECTED.get(
2385                      String.valueOf(result), result.getEntryCount()));
2386          }
2387          else
2388          {
2389            throw new AssertionError(
2390                 ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_MULTI_EXPECTED.get(
2391                      expectedEntryCount, String.valueOf(result),
2392                      result.getEntryCount()));
2393          }
2394        }
2395      }
2396    
2397    
2398    
2399      /**
2400       * Ensures that the provided search exception indicates that the expected
2401       * number of entries were returned.
2402       *
2403       * @param  exception           The search exception to examine.
2404       * @param  expectedEntryCount  The number of expected search result entries.
2405       *
2406       * @throws  AssertionError  If the number of entries returned does not match
2407       *                          the expected value.
2408       */
2409      public static void assertEntriesReturnedEquals(
2410                              final LDAPSearchException exception,
2411                              final int expectedEntryCount)
2412             throws AssertionError
2413      {
2414        if (exception.getEntryCount() != expectedEntryCount)
2415        {
2416          if (expectedEntryCount == 1)
2417          {
2418            throw new AssertionError(
2419                 ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_ONE_EXPECTED.get(
2420                      StaticUtils.getExceptionMessage(exception),
2421                      exception.getEntryCount()));
2422          }
2423          else
2424          {
2425            throw new AssertionError(
2426                 ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_MULTI_EXPECTED.get(
2427                      expectedEntryCount,
2428                      StaticUtils.getExceptionMessage(exception),
2429                      exception.getEntryCount()));
2430          }
2431        }
2432      }
2433    
2434    
2435    
2436      /**
2437       * Ensures that the provided search result indicates that at least one search
2438       * result reference was returned.
2439       *
2440       * @param  result  The search result to examine.
2441       *
2442       * @return  The number of search result references that were returned.
2443       *
2444       * @throws  AssertionError  If the provided search result indicates that no
2445       *                          references were returned.
2446       */
2447      public static int assertReferenceReturned(final SearchResult result)
2448             throws AssertionError
2449      {
2450        if (result.getReferenceCount() == 0)
2451        {
2452          throw new AssertionError(ERR_TEST_SEARCH_NO_REFS_RETURNED.get(
2453               String.valueOf(result)));
2454        }
2455    
2456        return result.getReferenceCount();
2457      }
2458    
2459    
2460    
2461      /**
2462       * Ensures that the provided search exception indicates that at least one
2463       * search result reference was returned.
2464       *
2465       * @param  exception  The search exception to examine.
2466       *
2467       * @return  The number of search result references that were returned.
2468       *
2469       * @throws  AssertionError  If the provided search exception indicates that no
2470       *                          references were returned.
2471       */
2472      public static int assertReferenceReturned(final LDAPSearchException exception)
2473             throws AssertionError
2474      {
2475        if (exception.getReferenceCount() == 0)
2476        {
2477          throw new AssertionError(ERR_TEST_SEARCH_NO_REFS_RETURNED.get(
2478               StaticUtils.getExceptionMessage(exception)));
2479        }
2480    
2481        return exception.getReferenceCount();
2482      }
2483    
2484    
2485    
2486      /**
2487       * Ensures that the provided search result indicates that no search result
2488       * references were returned.
2489       *
2490       * @param  result  The search result to examine.
2491       *
2492       * @throws  AssertionError  If the provided search result indicates that one
2493       *                          or more references were returned.
2494       */
2495      public static void assertNoReferencesReturned(final SearchResult result)
2496             throws AssertionError
2497      {
2498        if (result.getReferenceCount() > 0)
2499        {
2500          throw new AssertionError(ERR_TEST_SEARCH_REFS_RETURNED.get(
2501               String.valueOf(result), result.getReferenceCount()));
2502        }
2503      }
2504    
2505    
2506    
2507      /**
2508       * Ensures that the provided search exception indicates that no search result
2509       * references were returned.
2510       *
2511       * @param  exception  The search exception to examine.
2512       *
2513       * @throws  AssertionError  If the provided search exception indicates that
2514       *                          one or more references were returned.
2515       */
2516      public static void assertNoReferencesReturned(
2517                              final LDAPSearchException exception)
2518             throws AssertionError
2519      {
2520        if (exception.getReferenceCount() > 0)
2521        {
2522          throw new AssertionError(ERR_TEST_SEARCH_REFS_RETURNED.get(
2523               StaticUtils.getExceptionMessage(exception),
2524               exception.getReferenceCount()));
2525        }
2526      }
2527    
2528    
2529    
2530      /**
2531       * Ensures that the provided search result indicates that the expected number
2532       * of references were returned.
2533       *
2534       * @param  result                  The search result to examine.
2535       * @param  expectedReferenceCount  The number of expected search result
2536       *                                 references.
2537       *
2538       * @throws  AssertionError  If the number of references returned does not
2539       *                          match the expected value.
2540       */
2541      public static void assertReferencesReturnedEquals(final SearchResult result,
2542                              final int expectedReferenceCount)
2543             throws AssertionError
2544      {
2545        if (result.getReferenceCount() != expectedReferenceCount)
2546        {
2547          if (expectedReferenceCount == 1)
2548          {
2549            throw new AssertionError(
2550                 ERR_TEST_SEARCH_REF_COUNT_MISMATCH_ONE_EXPECTED.get(
2551                      String.valueOf(result), result.getReferenceCount()));
2552          }
2553          else
2554          {
2555            throw new AssertionError(
2556                 ERR_TEST_SEARCH_REF_COUNT_MISMATCH_MULTI_EXPECTED.get(
2557                      expectedReferenceCount, String.valueOf(result),
2558                      result.getReferenceCount()));
2559          }
2560        }
2561      }
2562    
2563    
2564    
2565      /**
2566       * Ensures that the provided search exception indicates that the expected
2567       * number of references were returned.
2568       *
2569       * @param  exception               The search exception to examine.
2570       * @param  expectedReferenceCount  The number of expected search result
2571       *                                 references.
2572       *
2573       * @throws  AssertionError  If the number of references returned does not
2574       *                          match the expected value.
2575       */
2576      public static void assertReferencesReturnedEquals(
2577                              final LDAPSearchException exception,
2578                              final int expectedReferenceCount)
2579             throws AssertionError
2580      {
2581        if (exception.getReferenceCount() != expectedReferenceCount)
2582        {
2583          if (expectedReferenceCount == 1)
2584          {
2585            throw new AssertionError(
2586                 ERR_TEST_SEARCH_REF_COUNT_MISMATCH_ONE_EXPECTED.get(
2587                      StaticUtils.getExceptionMessage(exception),
2588                      exception.getReferenceCount()));
2589          }
2590          else
2591          {
2592            throw new AssertionError(
2593                 ERR_TEST_SEARCH_REF_COUNT_MISMATCH_MULTI_EXPECTED.get(
2594                      expectedReferenceCount,
2595                      StaticUtils.getExceptionMessage(exception),
2596                      exception.getReferenceCount()));
2597          }
2598        }
2599      }
2600    
2601    
2602    
2603      /**
2604       * Ensures that the two provided strings represent the same DN.
2605       *
2606       * @param  s1  The first string to compare.
2607       * @param  s2  The second string to compare.
2608       *
2609       * @throws  AssertionError  If either string doesn't represent a valid DN, or
2610       *                          if they do not represent the same DN.
2611       */
2612      public static void assertDNsEqual(final String s1, final String s2)
2613             throws AssertionError
2614      {
2615        final DN dn1;
2616        try
2617        {
2618          dn1 = new DN(s1);
2619        }
2620        catch (final Exception e)
2621        {
2622          throw new AssertionError(ERR_TEST_VALUE_NOT_VALID_DN.get(s1,
2623               StaticUtils.getExceptionMessage(e)));
2624        }
2625    
2626        final DN dn2;
2627        try
2628        {
2629          dn2 = new DN(s2);
2630        }
2631        catch (final Exception e)
2632        {
2633          throw new AssertionError(ERR_TEST_VALUE_NOT_VALID_DN.get(s2,
2634               StaticUtils.getExceptionMessage(e)));
2635        }
2636    
2637        if (! dn1.equals(dn2))
2638        {
2639          throw new AssertionError(ERR_TEST_DNS_NOT_EQUAL.get(s1, s2));
2640        }
2641      }
2642    }