001/*
002 * Copyright 2011-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2011-2017 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 */
021package com.unboundid.util;
022
023
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collection;
028import java.util.List;
029
030import com.unboundid.ldap.matchingrules.DistinguishedNameMatchingRule;
031import com.unboundid.ldap.sdk.Attribute;
032import com.unboundid.ldap.sdk.Control;
033import com.unboundid.ldap.sdk.DN;
034import com.unboundid.ldap.sdk.Entry;
035import com.unboundid.ldap.sdk.Filter;
036import com.unboundid.ldap.sdk.LDAPConnection;
037import com.unboundid.ldap.sdk.LDAPException;
038import com.unboundid.ldap.sdk.LDAPInterface;
039import com.unboundid.ldap.sdk.LDAPRequest;
040import com.unboundid.ldap.sdk.LDAPResult;
041import com.unboundid.ldap.sdk.LDAPSearchException;
042import com.unboundid.ldap.sdk.RDN;
043import com.unboundid.ldap.sdk.ResultCode;
044import com.unboundid.ldap.sdk.SearchResult;
045import com.unboundid.ldap.sdk.SearchResultEntry;
046import com.unboundid.ldap.sdk.SearchResultReference;
047import com.unboundid.ldap.sdk.SearchScope;
048
049import 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)
058public 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}