001/*
002 * Copyright 2011-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2011-2019 Ping Identity Corporation
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<>(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<>(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<>(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().isEmpty())
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<>(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<>(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<>(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<>(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 = new ArrayList<>(attributeNames.size());
982
983    // We will use a separate search for each target attribute so that we can
984    // handle the case in which the attribute is present with a different name
985    // than the one provided.
986    for (final String attrName : attributeNames)
987    {
988      try
989      {
990        final SearchResult result = conn.search(dn, SearchScope.BASE,
991             Filter.createPresenceFilter(attrName));
992        if (result.getEntryCount() == 0)
993        {
994          missingAttrs.add(attrName);
995        }
996      }
997      catch (final LDAPException le)
998      {
999        if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1000        {
1001          return null;
1002        }
1003        else
1004        {
1005          throw le;
1006        }
1007      }
1008    }
1009
1010    return missingAttrs;
1011  }
1012
1013
1014
1015  /**
1016   * Ensures that the specified entry exists in the directory with all of the
1017   * specified attributes.
1018   *
1019   * @param  conn            The connection to use to communicate with the
1020   *                         directory server.
1021   * @param  dn              The DN of the entry to examine.
1022   * @param  attributeNames  The names of the attributes that are expected to be
1023   *                         present in the provided entry.
1024   *
1025   * @throws  LDAPException  If a problem is encountered while trying to
1026   *                         communicate with the directory server.
1027   *
1028   * @throws  AssertionError  If the target entry does not exist or does not
1029   *                          contain all of the specified attributes.
1030   */
1031  public static void assertAttributeExists(final LDAPInterface conn,
1032                                           final String dn,
1033                                           final String... attributeNames)
1034        throws LDAPException, AssertionError
1035  {
1036    assertAttributeExists(conn, dn, StaticUtils.toList(attributeNames));
1037  }
1038
1039
1040
1041  /**
1042   * Ensures that the specified entry exists in the directory with all of the
1043   * specified attributes.
1044   *
1045   * @param  conn            The connection to use to communicate with the
1046   *                         directory server.
1047   * @param  dn              The DN of the entry to examine.
1048   * @param  attributeNames  The names of the attributes that are expected to be
1049   *                         present in the provided entry.
1050   *
1051   * @throws  LDAPException  If a problem is encountered while trying to
1052   *                         communicate with the directory server.
1053   *
1054   * @throws  AssertionError  If the target entry does not exist or does not
1055   *                          contain all of the specified attributes.
1056   */
1057  public static void assertAttributeExists(final LDAPInterface conn,
1058                          final String dn,
1059                          final Collection<String> attributeNames)
1060        throws LDAPException, AssertionError
1061  {
1062    final List<String> missingAttrs =
1063         getMissingAttributeNames(conn, dn, attributeNames);
1064    if (missingAttrs == null)
1065    {
1066      // The target entry does not exist.
1067      throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1068    }
1069    else if (missingAttrs.isEmpty())
1070    {
1071      return;
1072    }
1073
1074    final List<String> msgList = new ArrayList<>(missingAttrs.size());
1075    for (final String attrName : missingAttrs)
1076    {
1077      msgList.add(ERR_TEST_ATTR_MISSING.get(dn, attrName));
1078    }
1079
1080    throw new AssertionError(StaticUtils.concatenateStrings(msgList));
1081  }
1082
1083
1084
1085  /**
1086   * Retrieves a list of all provided attribute values which are missing from
1087   * the specified entry.
1088   *
1089   * @param  conn             The connection to use to communicate with the
1090   *                          directory server.
1091   * @param  dn               The DN of the entry to examine.
1092   * @param  attributeName    The attribute expected to be present in the target
1093   *                          entry with the given values.
1094   * @param  attributeValues  The values expected to be present in the target
1095   *                          entry.
1096   *
1097   * @return  A list containing all of the provided values which were not found
1098   *          in the entry, an empty list if all provided attribute values were
1099   *          found, or {@code null} if the target entry does not exist.
1100   *
1101   * @throws  LDAPException  If a problem is encountered while trying to
1102   *                         communicate with the directory server.
1103   */
1104  public static List<String> getMissingAttributeValues(final LDAPInterface conn,
1105                                  final String dn, final String attributeName,
1106                                  final String... attributeValues)
1107         throws LDAPException
1108  {
1109    return getMissingAttributeValues(conn, dn, attributeName,
1110         StaticUtils.toList(attributeValues));
1111  }
1112
1113
1114
1115  /**
1116   * Retrieves a list of all provided attribute values which are missing from
1117   * the specified entry.  The target attribute may or may not contain
1118   * additional values.
1119   *
1120   * @param  conn             The connection to use to communicate with the
1121   *                          directory server.
1122   * @param  dn               The DN of the entry to examine.
1123   * @param  attributeName    The attribute expected to be present in the target
1124   *                          entry with the given values.
1125   * @param  attributeValues  The values expected to be present in the target
1126   *                          entry.
1127   *
1128   * @return  A list containing all of the provided values which were not found
1129   *          in the entry, an empty list if all provided attribute values were
1130   *          found, or {@code null} if the target entry does not exist.
1131   *
1132   * @throws  LDAPException  If a problem is encountered while trying to
1133   *                         communicate with the directory server.
1134   */
1135  public static List<String> getMissingAttributeValues(final LDAPInterface conn,
1136                                  final String dn, final String attributeName,
1137                                  final Collection<String> attributeValues)
1138       throws LDAPException
1139  {
1140    final List<String> missingValues = new ArrayList<>(attributeValues.size());
1141
1142    for (final String value : attributeValues)
1143    {
1144      try
1145      {
1146        final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1147             Filter.createEqualityFilter(attributeName, value), "1.1");
1148        if (searchResult.getEntryCount() == 0)
1149        {
1150          missingValues.add(value);
1151        }
1152      }
1153      catch (final LDAPException le)
1154      {
1155        if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1156        {
1157          return null;
1158        }
1159        else
1160        {
1161          throw le;
1162        }
1163      }
1164    }
1165
1166    return missingValues;
1167  }
1168
1169
1170
1171  /**
1172   * Ensures that the specified entry exists in the directory with all of the
1173   * specified values for the given attribute.  The attribute may or may not
1174   * contain additional values.
1175   *
1176   * @param  conn             The connection to use to communicate with the
1177   *                          directory server.
1178   * @param  dn               The DN of the entry to examine.
1179   * @param  attributeName    The name of the attribute to examine.
1180   * @param  attributeValues  The set of values which must exist for the given
1181   *                          attribute.
1182   *
1183   * @throws  LDAPException  If a problem is encountered while trying to
1184   *                         communicate with the directory server.
1185   *
1186   * @throws  AssertionError  If the target entry does not exist, does not
1187   *                          contain the specified attribute, or that attribute
1188   *                          does not have all of the specified values.
1189   */
1190  public static void assertValueExists(final LDAPInterface conn,
1191                                       final String dn,
1192                                       final String attributeName,
1193                                       final String... attributeValues)
1194        throws LDAPException, AssertionError
1195  {
1196    assertValueExists(conn, dn, attributeName,
1197         StaticUtils.toList(attributeValues));
1198  }
1199
1200
1201
1202  /**
1203   * Ensures that the specified entry exists in the directory with all of the
1204   * specified values for the given attribute.  The attribute may or may not
1205   * contain additional values.
1206   *
1207   * @param  conn             The connection to use to communicate with the
1208   *                          directory server.
1209   * @param  dn               The DN of the entry to examine.
1210   * @param  attributeName    The name of the attribute to examine.
1211   * @param  attributeValues  The set of values which must exist for the given
1212   *                          attribute.
1213   *
1214   * @throws  LDAPException  If a problem is encountered while trying to
1215   *                         communicate with the directory server.
1216   *
1217   * @throws  AssertionError  If the target entry does not exist, does not
1218   *                          contain the specified attribute, or that attribute
1219   *                          does not have all of the specified values.
1220   */
1221  public static void assertValueExists(final LDAPInterface conn,
1222                                       final String dn,
1223                                       final String attributeName,
1224                                       final Collection<String> attributeValues)
1225        throws LDAPException, AssertionError
1226  {
1227    final List<String> missingValues =
1228         getMissingAttributeValues(conn, dn, attributeName, attributeValues);
1229    if (missingValues == null)
1230    {
1231      // The target entry does not exist.
1232      throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1233    }
1234    else if (missingValues.isEmpty())
1235    {
1236      return;
1237    }
1238
1239    // Get the entry and see if the attribute exists in it at all.
1240    final Entry entry = conn.getEntry(dn, attributeName);
1241    if ((entry != null) && entry.hasAttribute(attributeName))
1242    {
1243      final Attribute a = entry.getAttribute(attributeName);
1244      throw new AssertionError(ERR_TEST_ATTR_MISSING_VALUE.get(dn,
1245           attributeName,
1246           StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1247                a.getValues()),
1248           StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1249                missingValues)));
1250    }
1251    else
1252    {
1253      throw new AssertionError(ERR_TEST_ATTR_MISSING.get(dn, attributeName));
1254    }
1255  }
1256
1257
1258
1259  /**
1260   * Ensures that the specified entry does not exist in the directory.
1261   *
1262   * @param  conn  The connection to use to communicate with the directory
1263   *               server.
1264   * @param  dn    The DN of the entry expected to be missing.
1265   *
1266   * @throws  LDAPException  If a problem is encountered while trying to
1267   *                         communicate with the directory server.
1268   *
1269   * @throws  AssertionError  If the target entry is found in the server.
1270   */
1271  public static void assertEntryMissing(final LDAPInterface conn,
1272                                        final String dn)
1273         throws LDAPException, AssertionError
1274  {
1275    if (conn.getEntry(dn, "1.1") != null)
1276    {
1277      throw new AssertionError(ERR_TEST_ENTRY_EXISTS.get(dn));
1278    }
1279  }
1280
1281
1282
1283  /**
1284   * Ensures that the specified entry exists in the directory but does not
1285   * contain any of the specified attributes.
1286   *
1287   * @param  conn            The connection to use to communicate with the
1288   *                         directory server.
1289   * @param  dn              The DN of the entry expected to be present.
1290   * @param  attributeNames  The names of the attributes expected to be missing
1291   *                         from the entry.
1292   *
1293   * @throws  LDAPException  If a problem is encountered while trying to
1294   *                         communicate with the directory server.
1295   *
1296   * @throws  AssertionError  If the target entry is missing from the server, or
1297   *                          if it contains any of the target attributes.
1298   */
1299  public static void assertAttributeMissing(final LDAPInterface conn,
1300                                            final String dn,
1301                                            final String... attributeNames)
1302         throws LDAPException, AssertionError
1303  {
1304    assertAttributeMissing(conn, dn, StaticUtils.toList(attributeNames));
1305  }
1306
1307
1308
1309  /**
1310   * Ensures that the specified entry exists in the directory but does not
1311   * contain any of the specified attributes.
1312   *
1313   * @param  conn            The connection to use to communicate with the
1314   *                         directory server.
1315   * @param  dn              The DN of the entry expected to be present.
1316   * @param  attributeNames  The names of the attributes expected to be missing
1317   *                         from the entry.
1318   *
1319   * @throws  LDAPException  If a problem is encountered while trying to
1320   *                         communicate with the directory server.
1321   *
1322   * @throws  AssertionError  If the target entry is missing from the server, or
1323   *                          if it contains any of the target attributes.
1324   */
1325  public static void assertAttributeMissing(final LDAPInterface conn,
1326                          final String dn,
1327                          final Collection<String> attributeNames)
1328         throws LDAPException, AssertionError
1329  {
1330    final List<String> messages = new ArrayList<>(attributeNames.size());
1331    for (final String attrName : attributeNames)
1332    {
1333      try
1334      {
1335        final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1336             Filter.createPresenceFilter(attrName), attrName);
1337        if (searchResult.getEntryCount() == 1)
1338        {
1339          final Attribute a =
1340               searchResult.getSearchEntries().get(0).getAttribute(attrName);
1341          if (a == null)
1342          {
1343            messages.add(ERR_TEST_ATTR_EXISTS.get(dn, attrName));
1344          }
1345          else
1346          {
1347            messages.add(ERR_TEST_ATTR_EXISTS_WITH_VALUES.get(dn, attrName,
1348                 StaticUtils.concatenateStrings("{", " '", ",", "'", " }",
1349                                 a.getValues())));
1350          }
1351        }
1352      }
1353      catch (final LDAPException le)
1354      {
1355        if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1356        {
1357          throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1358        }
1359        else
1360        {
1361          throw le;
1362        }
1363      }
1364    }
1365
1366    if (! messages.isEmpty())
1367    {
1368      throw new AssertionError(StaticUtils.concatenateStrings(messages));
1369    }
1370  }
1371
1372
1373
1374  /**
1375   * Ensures that the specified entry exists in the directory but does not
1376   * contain any of the specified attribute values.
1377   *
1378   * @param  conn             The connection to use to communicate with the
1379   *                          directory server.
1380   * @param  dn               The DN of the entry expected to be present.
1381   * @param  attributeName    The name of the attribute to examine.
1382   * @param  attributeValues  The values expected to be missing from the target
1383   *                          entry.
1384   *
1385   * @throws  LDAPException  If a problem is encountered while trying to
1386   *                         communicate with the directory server.
1387   *
1388   * @throws  AssertionError  If the target entry is missing from the server, or
1389   *                          if it contains any of the target attribute values.
1390   */
1391  public static void assertValueMissing(final LDAPInterface conn,
1392                          final String dn, final String attributeName,
1393                          final String... attributeValues)
1394         throws LDAPException, AssertionError
1395  {
1396    assertValueMissing(conn, dn, attributeName,
1397         StaticUtils.toList(attributeValues));
1398  }
1399
1400
1401
1402  /**
1403   * Ensures that the specified entry exists in the directory but does not
1404   * contain any of the specified attribute values.
1405   *
1406   * @param  conn             The connection to use to communicate with the
1407   *                          directory server.
1408   * @param  dn               The DN of the entry expected to be present.
1409   * @param  attributeName    The name of the attribute to examine.
1410   * @param  attributeValues  The values expected to be missing from the target
1411   *                          entry.
1412   *
1413   * @throws  LDAPException  If a problem is encountered while trying to
1414   *                         communicate with the directory server.
1415   *
1416   * @throws  AssertionError  If the target entry is missing from the server, or
1417   *                          if it contains any of the target attribute values.
1418   */
1419  public static void assertValueMissing(final LDAPInterface conn,
1420                          final String dn, final String attributeName,
1421                          final Collection<String> attributeValues)
1422         throws LDAPException, AssertionError
1423  {
1424    final List<String> messages = new ArrayList<>(attributeValues.size());
1425    for (final String value : attributeValues)
1426    {
1427      try
1428      {
1429        final SearchResult searchResult = conn.search(dn, SearchScope.BASE,
1430             Filter.createEqualityFilter(attributeName, value), "1.1");
1431        if (searchResult.getEntryCount() == 1)
1432        {
1433          messages.add(ERR_TEST_VALUE_EXISTS.get(dn, attributeName, value));
1434        }
1435      }
1436      catch (final LDAPException le)
1437      {
1438        if (le.getResultCode() == ResultCode.NO_SUCH_OBJECT)
1439        {
1440          throw new AssertionError(ERR_TEST_ENTRY_MISSING.get(dn));
1441        }
1442        else
1443        {
1444          throw le;
1445        }
1446      }
1447    }
1448
1449    if (! messages.isEmpty())
1450    {
1451      throw new AssertionError(StaticUtils.concatenateStrings(messages));
1452    }
1453  }
1454
1455
1456
1457  /**
1458   * Ensures that the result code for the provided result matches one of the
1459   * given acceptable result codes.
1460   *
1461   * @param  result                 The LDAP result to examine.
1462   * @param  acceptableResultCodes  The set of result codes that are considered
1463   *                                acceptable.
1464   *
1465   * @throws  AssertionError  If the result code from the provided result did
1466   *                          not match any of the acceptable values.
1467   */
1468  public static void assertResultCodeEquals(final LDAPResult result,
1469                          final ResultCode... acceptableResultCodes)
1470         throws AssertionError
1471  {
1472    for (final ResultCode rc : acceptableResultCodes)
1473    {
1474      if (rc.equals(result.getResultCode()))
1475      {
1476        return;
1477      }
1478    }
1479
1480    if (acceptableResultCodes.length == 1)
1481    {
1482      throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1483           String.valueOf(result), String.valueOf(acceptableResultCodes[0])));
1484    }
1485    else
1486    {
1487      throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1488           String.valueOf(result), Arrays.toString(acceptableResultCodes)));
1489    }
1490  }
1491
1492
1493
1494  /**
1495   * Ensures that the result code for the provided LDAP exception matches one of
1496   * the given acceptable result codes.
1497   *
1498   * @param  exception              The LDAP exception to examine.
1499   * @param  acceptableResultCodes  The set of result codes that are considered
1500   *                                acceptable.
1501   *
1502   * @throws  AssertionError  If the result code from the provided exception did
1503   *                          not match any of the acceptable values.
1504   */
1505  public static void assertResultCodeEquals(final LDAPException exception,
1506                          final ResultCode... acceptableResultCodes)
1507         throws AssertionError
1508  {
1509    for (final ResultCode rc : acceptableResultCodes)
1510    {
1511      if (rc.equals(exception.getResultCode()))
1512      {
1513        return;
1514      }
1515    }
1516
1517    if (acceptableResultCodes.length == 1)
1518    {
1519      throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1520           StaticUtils.getExceptionMessage(exception),
1521           String.valueOf(acceptableResultCodes[0])));
1522    }
1523    else
1524    {
1525      throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1526           StaticUtils.getExceptionMessage(exception),
1527           Arrays.toString(acceptableResultCodes)));
1528    }
1529  }
1530
1531
1532
1533  /**
1534   * Processes the provided request using the given connection and ensures that
1535   * the result code matches one of the provided acceptable values.
1536   *
1537   * @param  conn                   The connection to use to communicate with
1538   *                                the directory server.
1539   * @param  request                The request to be processed.
1540   * @param  acceptableResultCodes  The set of result codes that are considered
1541   *                                acceptable.
1542   *
1543   * @return  The result returned from processing the requested operation.
1544   *
1545   * @throws  AssertionError  If the result code returned by the server did not
1546   *                          match any acceptable values.
1547   */
1548  public static LDAPResult assertResultCodeEquals(final LDAPConnection conn,
1549                                final LDAPRequest request,
1550                                final ResultCode... acceptableResultCodes)
1551         throws AssertionError
1552  {
1553    LDAPResult result;
1554
1555    try
1556    {
1557      result = conn.processOperation(request);
1558    }
1559    catch (final LDAPException le)
1560    {
1561      result = le.toLDAPResult();
1562    }
1563
1564    for (final ResultCode rc : acceptableResultCodes)
1565    {
1566      if (rc.equals(result.getResultCode()))
1567      {
1568        return result;
1569      }
1570    }
1571
1572    if (acceptableResultCodes.length == 1)
1573    {
1574      throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_MISSING.get(
1575           String.valueOf(result), String.valueOf(acceptableResultCodes[0])));
1576    }
1577    else
1578    {
1579      throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_MISSING.get(
1580           String.valueOf(result), Arrays.toString(acceptableResultCodes)));
1581    }
1582  }
1583
1584
1585
1586  /**
1587   * Ensures that the result code for the provided result does not match any of
1588   * the given unacceptable result codes.
1589   *
1590   * @param  result                   The LDAP result to examine.
1591   * @param  unacceptableResultCodes  The set of result codes that are
1592   *                                  considered unacceptable.
1593   *
1594   * @throws  AssertionError  If the result code from the provided result
1595   *                          matched any of the unacceptable values.
1596   */
1597  public static void assertResultCodeNot(final LDAPResult result,
1598                          final ResultCode... unacceptableResultCodes)
1599         throws AssertionError
1600  {
1601    for (final ResultCode rc : unacceptableResultCodes)
1602    {
1603      if (rc.equals(result.getResultCode()))
1604      {
1605        if (unacceptableResultCodes.length == 1)
1606        {
1607          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1608               String.valueOf(result),
1609               String.valueOf(unacceptableResultCodes[0])));
1610        }
1611        else
1612        {
1613          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1614               String.valueOf(result),
1615               Arrays.toString(unacceptableResultCodes)));
1616        }
1617      }
1618    }
1619  }
1620
1621
1622
1623  /**
1624   * Ensures that the result code for the provided result does not match any of
1625   * the given unacceptable result codes.
1626   *
1627   * @param  exception                The LDAP exception to examine.
1628   * @param  unacceptableResultCodes  The set of result codes that are
1629   *                                  considered unacceptable.
1630   *
1631   * @throws  AssertionError  If the result code from the provided result
1632   *                          matched any of the unacceptable values.
1633   */
1634  public static void assertResultCodeNot(final LDAPException exception,
1635                          final ResultCode... unacceptableResultCodes)
1636         throws AssertionError
1637  {
1638    for (final ResultCode rc : unacceptableResultCodes)
1639    {
1640      if (rc.equals(exception.getResultCode()))
1641      {
1642        if (unacceptableResultCodes.length == 1)
1643        {
1644          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1645               StaticUtils.getExceptionMessage(exception),
1646               String.valueOf(unacceptableResultCodes[0])));
1647        }
1648        else
1649        {
1650          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1651               StaticUtils.getExceptionMessage(exception),
1652               Arrays.toString(unacceptableResultCodes)));
1653        }
1654      }
1655    }
1656  }
1657
1658
1659
1660  /**
1661   * Processes the provided request using the given connection and ensures that
1662   * the result code does not match any of the given unacceptable values.
1663   *
1664   * @param  conn                     The connection to use to communicate with
1665   *                                  the directory server.
1666   * @param  request                  The request to be processed.
1667   * @param  unacceptableResultCodes  The set of result codes that are
1668   *                                  considered unacceptable.
1669   *
1670   * @return  The result returned from processing the requested operation.
1671   *
1672   * @throws  AssertionError  If the result code from the provided result
1673   *                          matched any of the unacceptable values.
1674   */
1675  public static LDAPResult assertResultCodeNot(final LDAPConnection conn,
1676                                final LDAPRequest request,
1677                                final ResultCode... unacceptableResultCodes)
1678         throws AssertionError
1679  {
1680    LDAPResult result;
1681
1682    try
1683    {
1684      result = conn.processOperation(request);
1685    }
1686    catch (final LDAPException le)
1687    {
1688      result = le.toLDAPResult();
1689    }
1690
1691    for (final ResultCode rc : unacceptableResultCodes)
1692    {
1693      if (rc.equals(result.getResultCode()))
1694      {
1695        if (unacceptableResultCodes.length == 1)
1696        {
1697          throw new AssertionError(ERR_TEST_SINGLE_RESULT_CODE_FOUND.get(
1698               String.valueOf(result),
1699               String.valueOf(unacceptableResultCodes[0])));
1700        }
1701        else
1702        {
1703          throw new AssertionError(ERR_TEST_MULTI_RESULT_CODE_FOUND.get(
1704               String.valueOf(result),
1705               Arrays.toString(unacceptableResultCodes)));
1706        }
1707      }
1708    }
1709
1710    return result;
1711  }
1712
1713
1714
1715  /**
1716   * Ensures that the provided LDAP result contains a matched DN value.
1717   *
1718   * @param  result  The LDAP result to examine.
1719   *
1720   * @throws  AssertionError  If the provided result did not contain a matched
1721   *                          DN value.
1722   */
1723  public static void assertContainsMatchedDN(final LDAPResult result)
1724         throws AssertionError
1725  {
1726    if (result.getMatchedDN() == null)
1727    {
1728      throw new AssertionError(ERR_TEST_RESULT_MISSING_MATCHED_DN.get(
1729           String.valueOf(result)));
1730    }
1731  }
1732
1733
1734
1735  /**
1736   * Ensures that the provided LDAP exception contains a matched DN value.
1737   *
1738   * @param  exception  The LDAP exception to examine.
1739   *
1740   * @throws  AssertionError  If the provided exception did not contain a
1741   *                          matched DN value.
1742   */
1743  public static void assertContainsMatchedDN(final LDAPException exception)
1744         throws AssertionError
1745  {
1746    if (exception.getMatchedDN() == null)
1747    {
1748      throw new AssertionError(ERR_TEST_RESULT_MISSING_MATCHED_DN.get(
1749           StaticUtils.getExceptionMessage(exception)));
1750    }
1751  }
1752
1753
1754
1755  /**
1756   * Ensures that the provided LDAP result does not contain a matched DN value.
1757   *
1758   * @param  result  The LDAP result to examine.
1759   *
1760   * @throws  AssertionError  If the provided result contained a matched DN
1761   *                          value.
1762   */
1763  public static void assertMissingMatchedDN(final LDAPResult result)
1764         throws AssertionError
1765  {
1766    if (result.getMatchedDN() != null)
1767    {
1768      throw new AssertionError(ERR_TEST_RESULT_CONTAINS_MATCHED_DN.get(
1769           String.valueOf(result), result.getMatchedDN()));
1770    }
1771  }
1772
1773
1774
1775  /**
1776   * Ensures that the provided LDAP exception does not contain a matched DN
1777   * value.
1778   *
1779   * @param  exception  The LDAP exception to examine.
1780   *
1781   * @throws  AssertionError  If the provided exception contained a matched DN
1782   *                          value.
1783   */
1784  public static void assertMissingMatchedDN(final LDAPException exception)
1785         throws AssertionError
1786  {
1787    if (exception.getMatchedDN() != null)
1788    {
1789      throw new AssertionError(ERR_TEST_RESULT_CONTAINS_MATCHED_DN.get(
1790           StaticUtils.getExceptionMessage(exception),
1791           exception.getMatchedDN()));
1792    }
1793  }
1794
1795
1796
1797  /**
1798   * Ensures that the provided LDAP result has the given matched DN value.
1799   *
1800   * @param  result     The LDAP result to examine.
1801   * @param  matchedDN  The matched DN value expected to be found in the
1802   *                    provided result.  It must not be {@code null}.
1803   *
1804   * @throws  LDAPException  If either the found or expected matched DN values
1805   *                         could not be parsed as a valid DN.
1806   *
1807   * @throws  AssertionError  If the provided LDAP result did not contain a
1808   *                          matched DN, or if it had a matched DN that
1809   *                          differed from the expected value.
1810   */
1811  public static void assertMatchedDNEquals(final LDAPResult result,
1812                                           final String matchedDN)
1813         throws LDAPException, AssertionError
1814  {
1815    if (result.getMatchedDN() == null)
1816    {
1817      throw new AssertionError(ERR_TEST_RESULT_MISSING_EXPECTED_MATCHED_DN.get(
1818           String.valueOf(result), matchedDN));
1819    }
1820
1821    final DN foundDN    = new DN(result.getMatchedDN());
1822    final DN expectedDN = new DN(matchedDN);
1823    if (! foundDN.equals(expectedDN))
1824    {
1825      throw new AssertionError(ERR_TEST_MATCHED_DN_MISMATCH.get(
1826           String.valueOf(result), matchedDN, result.getMatchedDN()));
1827    }
1828  }
1829
1830
1831
1832  /**
1833   * Ensures that the provided LDAP exception has the given matched DN value.
1834   *
1835   * @param  exception  The LDAP exception to examine.
1836   * @param  matchedDN  The matched DN value expected to be found in the
1837   *                    provided exception.  It must not be {@code null}.
1838   *
1839   * @throws  LDAPException  If either the found or expected matched DN values
1840   *                         could not be parsed as a valid DN.
1841   *
1842   * @throws  AssertionError  If the provided LDAP exception did not contain a
1843   *                          matched DN, or if it had a matched DN that
1844   *                          differed from the expected value.
1845   */
1846  public static void assertMatchedDNEquals(final LDAPException exception,
1847                                           final String matchedDN)
1848         throws LDAPException, AssertionError
1849  {
1850    if (exception.getMatchedDN() == null)
1851    {
1852      throw new AssertionError(ERR_TEST_RESULT_MISSING_EXPECTED_MATCHED_DN.get(
1853           StaticUtils.getExceptionMessage(exception), matchedDN));
1854    }
1855
1856    final DN foundDN    = new DN(exception.getMatchedDN());
1857    final DN expectedDN = new DN(matchedDN);
1858    if (! foundDN.equals(expectedDN))
1859    {
1860      throw new AssertionError(ERR_TEST_MATCHED_DN_MISMATCH.get(
1861           StaticUtils.getExceptionMessage(exception), matchedDN,
1862           exception.getMatchedDN()));
1863    }
1864  }
1865
1866
1867
1868  /**
1869   * Ensures that the provided LDAP result contains a diagnostic message.
1870   *
1871   * @param  result  The LDAP result to examine.
1872   *
1873   * @throws  AssertionError  If the provided result did not contain a
1874   *                          diagnostic message.
1875   */
1876  public static void assertContainsDiagnosticMessage(final LDAPResult result)
1877         throws AssertionError
1878  {
1879    if (result.getDiagnosticMessage() == null)
1880    {
1881      throw new AssertionError(ERR_TEST_RESULT_MISSING_DIAGNOSTIC_MESSAGE.get(
1882           String.valueOf(result)));
1883    }
1884  }
1885
1886
1887
1888  /**
1889   * Ensures that the provided LDAP exception contains a diagnostic message.
1890   *
1891   * @param  exception  The LDAP exception to examine.
1892   *
1893   * @throws  AssertionError  If the provided exception did not contain a
1894   *                          diagnostic message.
1895   */
1896  public static void assertContainsDiagnosticMessage(
1897                          final LDAPException exception)
1898         throws AssertionError
1899  {
1900    if (exception.getDiagnosticMessage() == null)
1901    {
1902      throw new AssertionError(ERR_TEST_RESULT_MISSING_DIAGNOSTIC_MESSAGE.get(
1903           StaticUtils.getExceptionMessage(exception)));
1904    }
1905  }
1906
1907
1908
1909  /**
1910   * Ensures that the provided LDAP result does not contain a diagnostic
1911   * message.
1912   *
1913   * @param  result  The LDAP result to examine.
1914   *
1915   * @throws  AssertionError  If the provided result contained a diagnostic
1916   *                          message.
1917   */
1918  public static void assertMissingDiagnosticMessage(final LDAPResult result)
1919         throws AssertionError
1920  {
1921    if (result.getDiagnosticMessage() != null)
1922    {
1923      throw new AssertionError(ERR_TEST_RESULT_CONTAINS_DIAGNOSTIC_MESSAGE.get(
1924           String.valueOf(result), result.getDiagnosticMessage()));
1925    }
1926  }
1927
1928
1929
1930  /**
1931   * Ensures that the provided LDAP exception does not contain a diagnostic
1932   * message.
1933   *
1934   * @param  exception  The LDAP exception to examine.
1935   *
1936   * @throws  AssertionError  If the provided exception contained a diagnostic
1937   *                          message.
1938   */
1939  public static void assertMissingDiagnosticMessage(
1940                          final LDAPException exception)
1941         throws AssertionError
1942  {
1943    if (exception.getDiagnosticMessage() != null)
1944    {
1945      throw new AssertionError(ERR_TEST_RESULT_CONTAINS_DIAGNOSTIC_MESSAGE.get(
1946           StaticUtils.getExceptionMessage(exception),
1947           exception.getDiagnosticMessage()));
1948    }
1949  }
1950
1951
1952
1953  /**
1954   * Ensures that the provided LDAP result has the given diagnostic message.
1955   *
1956   * @param  result             The LDAP result to examine.
1957   * @param  diagnosticMessage  The diagnostic message expected to be found in
1958   *                            the provided result.  It must not be
1959   *                            {@code null}.
1960   *
1961   * @throws  AssertionError  If the provided LDAP result did not contain a
1962   *                          diagnostic message, or if it had a diagnostic
1963   *                          message that differed from the expected value.
1964   */
1965  public static void assertDiagnosticMessageEquals(final LDAPResult result,
1966                          final String diagnosticMessage)
1967         throws AssertionError
1968  {
1969    if (result.getDiagnosticMessage() == null)
1970    {
1971      throw new AssertionError(
1972           ERR_TEST_RESULT_MISSING_EXPECTED_DIAGNOSTIC_MESSAGE.get(
1973                String.valueOf(result), diagnosticMessage));
1974    }
1975
1976    if (! result.getDiagnosticMessage().equals(diagnosticMessage))
1977    {
1978      throw new AssertionError(ERR_TEST_DIAGNOSTIC_MESSAGE_MISMATCH.get(
1979           String.valueOf(result), diagnosticMessage,
1980           result.getDiagnosticMessage()));
1981    }
1982  }
1983
1984
1985
1986  /**
1987   * Ensures that the provided LDAP exception has the given diagnostic message.
1988   *
1989   * @param  exception          The LDAP exception to examine.
1990   * @param  diagnosticMessage  The diagnostic message expected to be found in
1991   *                            the provided exception.  It must not be
1992   *                            {@code null}.
1993   *
1994   * @throws  AssertionError  If the provided LDAP exception did not contain a
1995   *                          diagnostic message, or if it had a diagnostic
1996   *                          message that differed from the expected value.
1997   */
1998  public static void assertDiagnosticMessageEquals(
1999                          final LDAPException exception,
2000                          final String diagnosticMessage)
2001         throws AssertionError
2002  {
2003    if (exception.getDiagnosticMessage() == null)
2004    {
2005      throw new AssertionError(
2006           ERR_TEST_RESULT_MISSING_EXPECTED_DIAGNOSTIC_MESSAGE.get(
2007                StaticUtils.getExceptionMessage(exception), diagnosticMessage));
2008    }
2009
2010    if (! exception.getDiagnosticMessage().equals(diagnosticMessage))
2011    {
2012      throw new AssertionError(ERR_TEST_DIAGNOSTIC_MESSAGE_MISMATCH.get(
2013           StaticUtils.getExceptionMessage(exception), diagnosticMessage,
2014           exception.getDiagnosticMessage()));
2015    }
2016  }
2017
2018
2019
2020  /**
2021   * Ensures that the provided LDAP result has one or more referral URLs.
2022   *
2023   * @param  result  The LDAP result to examine.
2024   *
2025   * @throws  AssertionError  If the provided result does not have any referral
2026   *                          URLs.
2027   */
2028  public static void assertHasReferral(final LDAPResult result)
2029         throws AssertionError
2030  {
2031    final String[] referralURLs = result.getReferralURLs();
2032    if ((referralURLs == null) || (referralURLs.length == 0))
2033    {
2034      throw new AssertionError(ERR_TEST_RESULT_MISSING_REFERRAL.get(
2035           String.valueOf(result)));
2036    }
2037  }
2038
2039
2040
2041  /**
2042   * Ensures that the provided LDAP exception has one or more referral URLs.
2043   *
2044   * @param  exception  The LDAP exception to examine.
2045   *
2046   * @throws  AssertionError  If the provided exception does not have any
2047   *                          referral URLs.
2048   */
2049  public static void assertHasReferral(final LDAPException exception)
2050         throws AssertionError
2051  {
2052    final String[] referralURLs = exception.getReferralURLs();
2053    if ((referralURLs == null) || (referralURLs.length == 0))
2054    {
2055      throw new AssertionError(ERR_TEST_RESULT_MISSING_REFERRAL.get(
2056           StaticUtils.getExceptionMessage(exception)));
2057    }
2058  }
2059
2060
2061
2062  /**
2063   * Ensures that the provided LDAP result does not have any referral URLs.
2064   *
2065   * @param  result  The LDAP result to examine.
2066   *
2067   * @throws  AssertionError  If the provided result has one or more referral
2068   *                          URLs.
2069   */
2070  public static void assertMissingReferral(final LDAPResult result)
2071         throws AssertionError
2072  {
2073    final String[] referralURLs = result.getReferralURLs();
2074    if ((referralURLs != null) && (referralURLs.length > 0))
2075    {
2076      throw new AssertionError(ERR_TEST_RESULT_HAS_REFERRAL.get(
2077           String.valueOf(result)));
2078    }
2079  }
2080
2081
2082
2083  /**
2084   * Ensures that the provided LDAP exception does not have any referral URLs.
2085   *
2086   * @param  exception  The LDAP exception to examine.
2087   *
2088   * @throws  AssertionError  If the provided exception has one or more referral
2089   *                          URLs.
2090   */
2091  public static void assertMissingReferral(final LDAPException exception)
2092         throws AssertionError
2093  {
2094    final String[] referralURLs = exception.getReferralURLs();
2095    if ((referralURLs != null) && (referralURLs.length > 0))
2096    {
2097      throw new AssertionError(ERR_TEST_RESULT_HAS_REFERRAL.get(
2098           StaticUtils.getExceptionMessage(exception)));
2099    }
2100  }
2101
2102
2103
2104  /**
2105   * Ensures that the provided LDAP result includes at least one control with
2106   * the specified OID.
2107   *
2108   * @param  result  The LDAP result to examine.
2109   * @param  oid     The OID of the control which is expected to be present in
2110   *                 the result.
2111   *
2112   * @return  The first control found with the specified OID.
2113   *
2114   * @throws  AssertionError  If the provided LDAP result does not include any
2115   *                          control with the specified OID.
2116   */
2117  public static Control assertHasControl(final LDAPResult result,
2118                                         final String oid)
2119         throws AssertionError
2120  {
2121    for (final Control c : result.getResponseControls())
2122    {
2123      if (c.getOID().equals(oid))
2124      {
2125        return c;
2126      }
2127    }
2128
2129    throw new AssertionError(ERR_TEST_RESULT_MISSING_CONTROL.get(
2130         String.valueOf(result), oid));
2131  }
2132
2133
2134
2135  /**
2136   * Ensures that the provided LDAP exception includes at least one control with
2137   * the specified OID.
2138   *
2139   * @param  exception  The LDAP exception to examine.
2140   * @param  oid        The OID of the control which is expected to be present
2141   *                    in the exception.
2142   *
2143   * @return  The first control found with the specified OID.
2144   *
2145   * @throws  AssertionError  If the provided LDAP exception does not include
2146   *                          any control with the specified OID.
2147   */
2148  public static Control assertHasControl(final LDAPException exception,
2149                                         final String oid)
2150         throws AssertionError
2151  {
2152    for (final Control c : exception.getResponseControls())
2153    {
2154      if (c.getOID().equals(oid))
2155      {
2156        return c;
2157      }
2158    }
2159
2160    throw new AssertionError(ERR_TEST_RESULT_MISSING_CONTROL.get(
2161         StaticUtils.getExceptionMessage(exception), oid));
2162  }
2163
2164
2165
2166  /**
2167   * Ensures that the provided search result entry includes at least one control
2168   * with the specified OID.
2169   *
2170   * @param  entry  The search result entry to examine.
2171   * @param  oid    The OID of the control which is expected to be present in
2172   *                the search result entry.
2173   *
2174   * @return  The first control found with the specified OID.
2175   *
2176   * @throws  AssertionError  If the provided search result entry does not
2177   *                          include any control with the specified OID.
2178   */
2179  public static Control assertHasControl(final SearchResultEntry entry,
2180                                         final String oid)
2181         throws AssertionError
2182  {
2183    for (final Control c : entry.getControls())
2184    {
2185      if (c.getOID().equals(oid))
2186      {
2187        return c;
2188      }
2189    }
2190
2191    throw new AssertionError(ERR_TEST_ENTRY_MISSING_CONTROL.get(
2192         String.valueOf(entry), oid));
2193  }
2194
2195
2196
2197  /**
2198   * Ensures that the provided search result reference includes at least one
2199   * control with the specified OID.
2200   *
2201   * @param  reference  The search result reference to examine.
2202   * @param  oid        The OID of the control which is expected to be present
2203   *                    in the search result reference.
2204   *
2205   * @return  The first control found with the specified OID.
2206   *
2207   * @throws  AssertionError  If the provided search result reference does not
2208   *                          include any control with the specified OID.
2209   */
2210  public static Control assertHasControl(final SearchResultReference reference,
2211                                         final String oid)
2212         throws AssertionError
2213  {
2214    for (final Control c : reference.getControls())
2215    {
2216      if (c.getOID().equals(oid))
2217      {
2218        return c;
2219      }
2220    }
2221
2222    throw new AssertionError(ERR_TEST_REF_MISSING_CONTROL.get(
2223         String.valueOf(reference), oid));
2224  }
2225
2226
2227
2228  /**
2229   * Ensures that the provided LDAP result does not include any control with
2230   * the specified OID.
2231   *
2232   * @param  result  The LDAP result to examine.
2233   * @param  oid     The OID of the control which is not expected to be present
2234   *                 in the result.
2235   *
2236   * @throws  AssertionError  If the provided LDAP result includes any control
2237   *                          with the specified OID.
2238   */
2239  public static void assertMissingControl(final LDAPResult result,
2240                                          final String oid)
2241         throws AssertionError
2242  {
2243    for (final Control c : result.getResponseControls())
2244    {
2245      if (c.getOID().equals(oid))
2246      {
2247        throw new AssertionError(ERR_TEST_RESULT_HAS_CONTROL.get(
2248             String.valueOf(result), oid));
2249      }
2250    }
2251  }
2252
2253
2254
2255  /**
2256   * Ensures that the provided LDAP exception does not include any control with
2257   * the specified OID.
2258   *
2259   * @param  exception  The LDAP exception to examine.
2260   * @param  oid        The OID of the control which is not expected to be
2261   *                    present in the exception.
2262   *
2263   * @throws  AssertionError  If the provided LDAP exception includes any
2264   *                          control with the specified OID.
2265   */
2266  public static void assertMissingControl(final LDAPException exception,
2267                                          final String oid)
2268         throws AssertionError
2269  {
2270    for (final Control c : exception.getResponseControls())
2271    {
2272      if (c.getOID().equals(oid))
2273      {
2274        throw new AssertionError(ERR_TEST_RESULT_HAS_CONTROL.get(
2275             StaticUtils.getExceptionMessage(exception), oid));
2276      }
2277    }
2278  }
2279
2280
2281
2282  /**
2283   * Ensures that the provided search result entry does not includes any control
2284   * with the specified OID.
2285   *
2286   * @param  entry  The search result entry to examine.
2287   * @param  oid    The OID of the control which is not expected to be present
2288   *                in the search result entry.
2289   *
2290   * @throws  AssertionError  If the provided search result entry includes any
2291   *                          control with the specified OID.
2292   */
2293  public static void assertMissingControl(final SearchResultEntry entry,
2294                                          final String oid)
2295         throws AssertionError
2296  {
2297    for (final Control c : entry.getControls())
2298    {
2299      if (c.getOID().equals(oid))
2300      {
2301        throw new AssertionError(ERR_TEST_ENTRY_HAS_CONTROL.get(
2302             String.valueOf(entry), oid));
2303      }
2304    }
2305  }
2306
2307
2308
2309  /**
2310   * Ensures that the provided search result reference does not includes any
2311   * control with the specified OID.
2312   *
2313   * @param  reference  The search result reference to examine.
2314   * @param  oid        The OID of the control which is not expected to be
2315   *                    present in the search result reference.
2316   *
2317   * @throws  AssertionError  If the provided search result reference includes
2318   *                          any control with the specified OID.
2319   */
2320  public static void assertMissingControl(final SearchResultReference reference,
2321                                          final String oid)
2322         throws AssertionError
2323  {
2324    for (final Control c : reference.getControls())
2325    {
2326      if (c.getOID().equals(oid))
2327      {
2328        throw new AssertionError(ERR_TEST_REF_HAS_CONTROL.get(
2329             String.valueOf(reference), oid));
2330      }
2331    }
2332  }
2333
2334
2335
2336  /**
2337   * Ensures that the provided search result indicates that at least one search
2338   * result entry was returned.
2339   *
2340   * @param  result  The search result to examine.
2341   *
2342   * @return  The number of search result entries that were returned.
2343   *
2344   * @throws  AssertionError  If the provided search result indicates that no
2345   *                          entries were returned.
2346   */
2347  public static int assertEntryReturned(final SearchResult result)
2348         throws AssertionError
2349  {
2350    if (result.getEntryCount() == 0)
2351    {
2352      throw new AssertionError(ERR_TEST_SEARCH_NO_ENTRIES_RETURNED.get(
2353           String.valueOf(result)));
2354    }
2355
2356    return result.getEntryCount();
2357  }
2358
2359
2360
2361  /**
2362   * Ensures that the provided search exception indicates that at least one
2363   * search result entry was returned.
2364   *
2365   * @param  exception  The search exception to examine.
2366   *
2367   * @return  The number of search result entries that were returned.
2368   *
2369   * @throws  AssertionError  If the provided search exception indicates that no
2370   *                          entries were returned.
2371   */
2372  public static int assertEntryReturned(final LDAPSearchException exception)
2373         throws AssertionError
2374  {
2375    if (exception.getEntryCount() == 0)
2376    {
2377      throw new AssertionError(ERR_TEST_SEARCH_NO_ENTRIES_RETURNED.get(
2378           StaticUtils.getExceptionMessage(exception)));
2379    }
2380
2381    return exception.getEntryCount();
2382  }
2383
2384
2385
2386  /**
2387   * Ensures that the specified search result entry was included in provided
2388   * search result.
2389   *
2390   * @param  result  The search result to examine.
2391   * @param  dn      The DN of the entry expected to be included in the
2392   *                 search result.
2393   *
2394   * @return  The search result entry with the provided DN.
2395   *
2396   * @throws  LDAPException  If the provided string cannot be parsed as a valid
2397   *                         DN.
2398   *
2399   * @throws  AssertionError  If the specified entry was not included in the
2400   *                          set of entries that were returned, or if a search
2401   *                          result listener was used which makes the
2402   *                          determination impossible.
2403   */
2404  public static SearchResultEntry assertEntryReturned(final SearchResult result,
2405                                                      final String dn)
2406         throws LDAPException, AssertionError
2407  {
2408    final DN parsedDN = new DN(dn);
2409
2410    final List<SearchResultEntry> entryList = result.getSearchEntries();
2411    if (entryList != null)
2412    {
2413      for (final SearchResultEntry e : entryList)
2414      {
2415        if (e.getParsedDN().equals(parsedDN))
2416        {
2417          return e;
2418        }
2419      }
2420    }
2421
2422    throw new AssertionError(ERR_TEST_SEARCH_ENTRY_NOT_RETURNED.get(
2423         String.valueOf(result), dn));
2424  }
2425
2426
2427
2428  /**
2429   * Ensures that the specified search result entry was included in provided
2430   * search exception.
2431   *
2432   * @param  exception  The search exception to examine.
2433   * @param  dn         The DN of the entry expected to be included in the
2434   *                    search exception.
2435   *
2436   * @return  The search result entry with the provided DN.
2437   *
2438   * @throws  LDAPException  If the provided string cannot be parsed as a valid
2439   *                         DN.
2440   *
2441   * @throws  AssertionError  If the specified entry was not included in the
2442   *                          set of entries that were returned, or if a search
2443   *                          result listener was used which makes the
2444   *                          determination impossible.
2445   */
2446  public static SearchResultEntry assertEntryReturned(
2447                                       final LDAPSearchException exception,
2448                                       final String dn)
2449         throws LDAPException, AssertionError
2450  {
2451    final DN parsedDN = new DN(dn);
2452
2453    final List<SearchResultEntry> entryList = exception.getSearchEntries();
2454    if (entryList != null)
2455    {
2456      for (final SearchResultEntry e : entryList)
2457      {
2458        if (e.getParsedDN().equals(parsedDN))
2459        {
2460          return e;
2461        }
2462      }
2463    }
2464
2465    throw new AssertionError(ERR_TEST_SEARCH_ENTRY_NOT_RETURNED.get(
2466         StaticUtils.getExceptionMessage(exception), dn));
2467  }
2468
2469
2470
2471  /**
2472   * Ensures that the provided search result indicates that no search result
2473   * entries were returned.
2474   *
2475   * @param  result  The search result to examine.
2476   *
2477   * @throws  AssertionError  If the provided search result indicates that one
2478   *                          or more entries were returned.
2479   */
2480  public static void assertNoEntriesReturned(final SearchResult result)
2481         throws AssertionError
2482  {
2483    if (result.getEntryCount() > 0)
2484    {
2485      throw new AssertionError(ERR_TEST_SEARCH_ENTRIES_RETURNED.get(
2486           String.valueOf(result), result.getEntryCount()));
2487    }
2488  }
2489
2490
2491
2492  /**
2493   * Ensures that the provided search exception indicates that no search result
2494   * entries were returned.
2495   *
2496   * @param  exception  The search exception to examine.
2497   *
2498   * @throws  AssertionError  If the provided search exception indicates that
2499   *                          one or more entries were returned.
2500   */
2501  public static void assertNoEntriesReturned(
2502                          final LDAPSearchException exception)
2503         throws AssertionError
2504  {
2505    if (exception.getEntryCount() > 0)
2506    {
2507      throw new AssertionError(ERR_TEST_SEARCH_ENTRIES_RETURNED.get(
2508           StaticUtils.getExceptionMessage(exception),
2509           exception.getEntryCount()));
2510    }
2511  }
2512
2513
2514
2515  /**
2516   * Ensures that the provided search result indicates that the expected number
2517   * of entries were returned.
2518   *
2519   * @param  result              The search result to examine.
2520   * @param  expectedEntryCount  The number of expected search result entries.
2521   *
2522   * @throws  AssertionError  If the number of entries returned does not match
2523   *                          the expected value.
2524   */
2525  public static void assertEntriesReturnedEquals(final SearchResult result,
2526                                                 final int expectedEntryCount)
2527         throws AssertionError
2528  {
2529    if (result.getEntryCount() != expectedEntryCount)
2530    {
2531      if (expectedEntryCount == 1)
2532      {
2533        throw new AssertionError(
2534             ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_ONE_EXPECTED.get(
2535                  String.valueOf(result), result.getEntryCount()));
2536      }
2537      else
2538      {
2539        throw new AssertionError(
2540             ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_MULTI_EXPECTED.get(
2541                  expectedEntryCount, String.valueOf(result),
2542                  result.getEntryCount()));
2543      }
2544    }
2545  }
2546
2547
2548
2549  /**
2550   * Ensures that the provided search exception indicates that the expected
2551   * number of entries were returned.
2552   *
2553   * @param  exception           The search exception to examine.
2554   * @param  expectedEntryCount  The number of expected search result entries.
2555   *
2556   * @throws  AssertionError  If the number of entries returned does not match
2557   *                          the expected value.
2558   */
2559  public static void assertEntriesReturnedEquals(
2560                          final LDAPSearchException exception,
2561                          final int expectedEntryCount)
2562         throws AssertionError
2563  {
2564    if (exception.getEntryCount() != expectedEntryCount)
2565    {
2566      if (expectedEntryCount == 1)
2567      {
2568        throw new AssertionError(
2569             ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_ONE_EXPECTED.get(
2570                  StaticUtils.getExceptionMessage(exception),
2571                  exception.getEntryCount()));
2572      }
2573      else
2574      {
2575        throw new AssertionError(
2576             ERR_TEST_SEARCH_ENTRY_COUNT_MISMATCH_MULTI_EXPECTED.get(
2577                  expectedEntryCount,
2578                  StaticUtils.getExceptionMessage(exception),
2579                  exception.getEntryCount()));
2580      }
2581    }
2582  }
2583
2584
2585
2586  /**
2587   * Ensures that the provided search result indicates that at least one search
2588   * result reference was returned.
2589   *
2590   * @param  result  The search result to examine.
2591   *
2592   * @return  The number of search result references that were returned.
2593   *
2594   * @throws  AssertionError  If the provided search result indicates that no
2595   *                          references were returned.
2596   */
2597  public static int assertReferenceReturned(final SearchResult result)
2598         throws AssertionError
2599  {
2600    if (result.getReferenceCount() == 0)
2601    {
2602      throw new AssertionError(ERR_TEST_SEARCH_NO_REFS_RETURNED.get(
2603           String.valueOf(result)));
2604    }
2605
2606    return result.getReferenceCount();
2607  }
2608
2609
2610
2611  /**
2612   * Ensures that the provided search exception indicates that at least one
2613   * search result reference was returned.
2614   *
2615   * @param  exception  The search exception to examine.
2616   *
2617   * @return  The number of search result references that were returned.
2618   *
2619   * @throws  AssertionError  If the provided search exception indicates that no
2620   *                          references were returned.
2621   */
2622  public static int assertReferenceReturned(final LDAPSearchException exception)
2623         throws AssertionError
2624  {
2625    if (exception.getReferenceCount() == 0)
2626    {
2627      throw new AssertionError(ERR_TEST_SEARCH_NO_REFS_RETURNED.get(
2628           StaticUtils.getExceptionMessage(exception)));
2629    }
2630
2631    return exception.getReferenceCount();
2632  }
2633
2634
2635
2636  /**
2637   * Ensures that the provided search result indicates that no search result
2638   * references were returned.
2639   *
2640   * @param  result  The search result to examine.
2641   *
2642   * @throws  AssertionError  If the provided search result indicates that one
2643   *                          or more references were returned.
2644   */
2645  public static void assertNoReferencesReturned(final SearchResult result)
2646         throws AssertionError
2647  {
2648    if (result.getReferenceCount() > 0)
2649    {
2650      throw new AssertionError(ERR_TEST_SEARCH_REFS_RETURNED.get(
2651           String.valueOf(result), result.getReferenceCount()));
2652    }
2653  }
2654
2655
2656
2657  /**
2658   * Ensures that the provided search exception indicates that no search result
2659   * references were returned.
2660   *
2661   * @param  exception  The search exception to examine.
2662   *
2663   * @throws  AssertionError  If the provided search exception indicates that
2664   *                          one or more references were returned.
2665   */
2666  public static void assertNoReferencesReturned(
2667                          final LDAPSearchException exception)
2668         throws AssertionError
2669  {
2670    if (exception.getReferenceCount() > 0)
2671    {
2672      throw new AssertionError(ERR_TEST_SEARCH_REFS_RETURNED.get(
2673           StaticUtils.getExceptionMessage(exception),
2674           exception.getReferenceCount()));
2675    }
2676  }
2677
2678
2679
2680  /**
2681   * Ensures that the provided search result indicates that the expected number
2682   * of references were returned.
2683   *
2684   * @param  result                  The search result to examine.
2685   * @param  expectedReferenceCount  The number of expected search result
2686   *                                 references.
2687   *
2688   * @throws  AssertionError  If the number of references returned does not
2689   *                          match the expected value.
2690   */
2691  public static void assertReferencesReturnedEquals(final SearchResult result,
2692                          final int expectedReferenceCount)
2693         throws AssertionError
2694  {
2695    if (result.getReferenceCount() != expectedReferenceCount)
2696    {
2697      if (expectedReferenceCount == 1)
2698      {
2699        throw new AssertionError(
2700             ERR_TEST_SEARCH_REF_COUNT_MISMATCH_ONE_EXPECTED.get(
2701                  String.valueOf(result), result.getReferenceCount()));
2702      }
2703      else
2704      {
2705        throw new AssertionError(
2706             ERR_TEST_SEARCH_REF_COUNT_MISMATCH_MULTI_EXPECTED.get(
2707                  expectedReferenceCount, String.valueOf(result),
2708                  result.getReferenceCount()));
2709      }
2710    }
2711  }
2712
2713
2714
2715  /**
2716   * Ensures that the provided search exception indicates that the expected
2717   * number of references were returned.
2718   *
2719   * @param  exception               The search exception to examine.
2720   * @param  expectedReferenceCount  The number of expected search result
2721   *                                 references.
2722   *
2723   * @throws  AssertionError  If the number of references returned does not
2724   *                          match the expected value.
2725   */
2726  public static void assertReferencesReturnedEquals(
2727                          final LDAPSearchException exception,
2728                          final int expectedReferenceCount)
2729         throws AssertionError
2730  {
2731    if (exception.getReferenceCount() != expectedReferenceCount)
2732    {
2733      if (expectedReferenceCount == 1)
2734      {
2735        throw new AssertionError(
2736             ERR_TEST_SEARCH_REF_COUNT_MISMATCH_ONE_EXPECTED.get(
2737                  StaticUtils.getExceptionMessage(exception),
2738                  exception.getReferenceCount()));
2739      }
2740      else
2741      {
2742        throw new AssertionError(
2743             ERR_TEST_SEARCH_REF_COUNT_MISMATCH_MULTI_EXPECTED.get(
2744                  expectedReferenceCount,
2745                  StaticUtils.getExceptionMessage(exception),
2746                  exception.getReferenceCount()));
2747      }
2748    }
2749  }
2750
2751
2752
2753  /**
2754   * Ensures that the two provided strings represent the same DN.
2755   *
2756   * @param  s1  The first string to compare.
2757   * @param  s2  The second string to compare.
2758   *
2759   * @throws  AssertionError  If either string doesn't represent a valid DN, or
2760   *                          if they do not represent the same DN.
2761   */
2762  public static void assertDNsEqual(final String s1, final String s2)
2763         throws AssertionError
2764  {
2765    final DN dn1;
2766    try
2767    {
2768      dn1 = new DN(s1);
2769    }
2770    catch (final Exception e)
2771    {
2772      throw new AssertionError(ERR_TEST_VALUE_NOT_VALID_DN.get(s1,
2773           StaticUtils.getExceptionMessage(e)));
2774    }
2775
2776    final DN dn2;
2777    try
2778    {
2779      dn2 = new DN(s2);
2780    }
2781    catch (final Exception e)
2782    {
2783      throw new AssertionError(ERR_TEST_VALUE_NOT_VALID_DN.get(s2,
2784           StaticUtils.getExceptionMessage(e)));
2785    }
2786
2787    if (! dn1.equals(dn2))
2788    {
2789      throw new AssertionError(ERR_TEST_DNS_NOT_EQUAL.get(s1, s2));
2790    }
2791  }
2792}