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