int main(int argc, char *argv[])
{
    int                 test = argc > 1 ? atoi(argv[1]) : 0;
    bool             verbose = argc > 2;
    bool         veryVerbose = argc > 3;
    bool     veryVeryVerbose = argc > 4;
    bool veryVeryVeryVerbose = argc > 5;

    (void)veryVeryVeryVerbose;  // suppress warning

    printf("TEST " __FILE__ " CASE %d\n", test);

    switch (test) { case 0:
      case 7: {
        // --------------------------------------------------------------------
        // USAGE EXAMPLE
        //   The hashing algorithm can be used to create more powerful
        //   components such as functors that can be used to power hash tables.
        //
        // Concerns:
        //: 1 The usage example provided in the component header file compiles,
        //:   links, and runs as shown.
        //
        // Plan:
        //: 1 Incorporate usage example from header into test driver (C-1)
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) printf("USAGE EXAMPLE\n"
                            "=============\n");

// Then, we want to actually use our hash table on 'Future' objects.  We create
// an array of 'Future's based on data that was originally from some external
// source:

        Future futures[] = { Future("Swiss Franc", 'F', 2014),
                             Future("US Dollar", 'G', 2015),
                             Future("Canadian Dollar", 'Z', 2014),
                             Future("British Pound", 'M', 2015),
                             Future("Deutsche Mark", 'X', 2016),
                             Future("Eurodollar", 'Q', 2017)};
        enum { NUM_FUTURES = sizeof futures / sizeof *futures };

// Next, we create our HashTable 'hashTable'.  We pass the functor that we
// defined above as the second argument:

        HashTable<Future, HashFuture> hashTable(futures, NUM_FUTURES);

// Now, we verify that each element in our array registers with count:
        for ( int i = 0; i < 6; ++i) {
            ASSERT(hashTable.contains(futures[i]));
        }

// Finally, we verify that futures not in our original array are correctly
// identified as not being in the set:

        ASSERT(!hashTable.contains(Future("French Franc", 'N', 2019)));
        ASSERT(!hashTable.contains(Future("Swiss Franc", 'X', 2014)));
        ASSERT(!hashTable.contains(Future("US Dollar", 'F', 2014)));

      } break;
      case 6: {
        // --------------------------------------------------------------------
        // TESTING BDE TYPE TRAITS
        //   The class is bitwise movable and should have a trait that
        //   indicates that.
        //
        // Concerns:
        //: 1 The class is marked as 'IsBitwiseMoveable'.
        //
        // Plan:
        //: 1 ASSERT the presence of the trait using the 'bslalg::HasTrait'
        //:   metafunction. (C-1)
        //
        // Testing:
        //   Trait IsBitwiseMoveable
        // --------------------------------------------------------------------

        if (verbose) printf("\nTESTING BDE TYPE TRAITS"
                            "\n=======================\n");

        if (verbose) printf("ASSERT the presence of the trait using the"
                            " 'bslalg::HasTrait' metafunction. (C-1)\n");
        {
            ASSERT(bslmf::IsBitwiseMoveable<SpookyHashAlgorithm>::value);
        }

      } break;
      case 5: {
        // --------------------------------------------------------------------
        // TESTING 'k_SEED_LENGTH'
        //   The class is a seeded algorithm and should expose a
        //   'k_SEED_LENGTH' enum.
        //
        // Concerns:
        //: 1 'k_SEED_LENGTH' is publicly accessible.
        //:
        //: 2 'k_SEED_LENGTH' is set to 16.
        //
        // Plan:
        //: 1 Access 'k_SEED_LENGTH' and ASSERT it is equal to the expected
        //:   value. (C-1,2)
        //
        // Testing:
        //   enum { k_SEED_LENGTH = 16 };
        // --------------------------------------------------------------------

        if (verbose) printf("\nTESTING 'k_SEED_LENGTH'"
                            "\n=======================\n");

        if (verbose) printf("Access 'k_SEED_LENGTH' and ASSERT it is equal to"
                            " the expected value. (C-1,2)\n");
        {
            ASSERT(16 == SpookyHashAlgorithm::k_SEED_LENGTH);
        }

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // TESTING 'result_type' TYPEDEF
        //   Verify that the class offers the result_type typedef that needs to
        //   be exposed by all 'bslh' hashing algorithms
        //
        // Concerns:
        //: 1 The typedef 'result_type' is publicly accessible and an alias for
        //:   'bsls::Types::Uint64'.
        //:
        //: 2 'computeHash()' returns 'result_type'
        //
        // Plan:
        //: 1 ASSERT the typedef is accessible and is the correct type using
        //:   'bslmf::IsSame'. (C-1)
        //:
        //: 2 Declare the expected signature of 'computeHash()' and then assign
        //:   to it.  If it compiles, the test passes. (C-2)
        //
        // Testing:
        //   typedef bsls::Types::Uint64 result_type;
        // --------------------------------------------------------------------

        if (verbose) printf("\nTESTING 'result_type' TYPEDEF"
                            "\n=============================\n");

        if (verbose) printf("ASSERT the typedef is accessible and is the"
                            " correct type using 'bslmf::IsSame'. (C-1)\n");
        {
            ASSERT((bslmf::IsSame<bsls::Types::Uint64,
                                  Obj::result_type>::VALUE));
        }

        if (verbose) printf("Declare the expected signature of 'computeHash()'"
                            " and then assign to it.  If it compiles, the test"
                            " passes. (C-2)\n");
        {
            Obj::result_type (Obj::*expectedSignature) ();

            expectedSignature = &Obj::computeHash;
            (void)expectedSignature;
        }

      } break;
      case 3: {
        // --------------------------------------------------------------------
        // TESTING TESTING 'operator()' AND 'computeHash()'
        //   Verify the class provides an overload for the function call
        //   operator that can be called with some bytes and a length.  Verify
        //   that calling 'operator()' will permute the algorithm's internal
        //   state as specified by SpookyHash.  Verify that 'computeHash()'
        //   returns the final value specified by the canonical spooky hash
        //   implementation.
        //
        // Concerns:
        //: 1 The function call operator is callable.
        //:
        //: 2 Given the same bytes, the function call operator will permute the
        //:   internal state of the algorithm in the same way, regardless of
        //:   whether the bytes are passed in all at once or in pieces.
        //:
        //: 3 Byte sequences passed in to 'operator()' with a length of 0 will
        //:   not contribute to the final hash
        //:
        //: 4 'computeHash()' and returns the appropriate value
        //:   according to the SpookyHash specification.
        //:
        //: 5 'operator()' does a BSLS_ASSERT for null pointers.
        //
        // Plan:
        //: 1 Insert various lengths of c-strings into the algorithm both all
        //:   at once and char by char using 'operator()'.  Assert that the
        //:   algorithm produces the same result in both cases. (C-1,2)
        //:
        //: 2 Hash c-strings all at once and with multiple calls to
        //:   'operator()' with length 0.  Assert that both methods of hashing
        //:   c-strings produce the same values.(C-3)
        //:
        //: 3 Check the output of 'computeHash()' against the expected results
        //:   from a known good version of the algorithm. (C-4)
        //:
        //: 4 Call 'operator()' with a null pointer. (C-5)
        //
        // Testing:
        //   void operator()(void const* key, size_t len);
        //   result_type computeHash();
        // --------------------------------------------------------------------

        if (verbose) printf(
                       "\nTESTING TESTING 'operator()' AND 'computeHash()'"
                       "\n================================================\n");

        static const struct {
            int                  d_line;
            const char           d_value [21];
            bsls::Types::Uint64  d_expectedHash;
        } DATA[] = {
#ifdef BSLS_PLATFORM_IS_LITTLE_ENDIAN
        // LINE DATA               HASH
         {  L_,                     "1",  7002407594712107506ULL,},
         {  L_,                    "12", 16818667202782586754ULL,},
         {  L_,                   "123", 14962907208936606339ULL,},
         {  L_,                  "1234", 13841264755844795919ULL,},
         {  L_,                 "12345",  4217007344502432836ULL,},
         {  L_,                "123456", 15406725965008216808ULL,},
         {  L_,               "1234567",  9451242472090273442ULL,},
         {  L_,              "12345678", 10759732512414454861ULL,},
         {  L_,             "123456789",   972485933408677714ULL,},
         {  L_,            "1234567890",  5673121172557267903ULL,},
         {  L_,           "12345678901", 13862553145028760004ULL,},
         {  L_,          "123456789012", 15680761296024743980ULL,},
         {  L_,         "1234567890123",  9130538754397985015ULL,},
         {  L_,        "12345678901234", 18108216297703361154ULL,},
         {  L_,       "123456789012345", 14690529358019617166ULL,},
         {  L_,      "1234567890123456", 10018078431842207320ULL,},
         {  L_,     "12345678901234567", 18401305144349413810ULL,},
         {  L_,    "123456789012345678", 16182063539957820126ULL,},
         {  L_,   "1234567890123456789", 16302264721124054926ULL,},
         {  L_,  "12345678901234567890",  7953951658377832965ULL,},
#else
        // LINE DATA               HASH
         {  L_,                     "1",  7002407594712107506ULL,},
         {  L_,                    "12", 16818667202782586754ULL,},
         {  L_,                   "123", 14962907208936606339ULL,},
         {  L_,                  "1234",  6699426530780107312ULL,},
         {  L_,                 "12345",  8676331252213764608ULL,},
         {  L_,                "123456",  4550369474379901410ULL,},
         {  L_,               "1234567", 16791262952135217002ULL,},
         {  L_,              "12345678", 16425013147235105742ULL,},
         {  L_,             "123456789",  5214485795892544707ULL,},
         {  L_,            "1234567890", 12261113520408985235ULL,},
         {  L_,           "12345678901",  2168166662679930866ULL,},
         {  L_,          "123456789012", 12754308552622014786ULL,},
         {  L_,         "1234567890123", 14297370022220374180ULL,},
         {  L_,        "12345678901234", 16893477830408992202ULL,},
         {  L_,       "123456789012345",  9435207994519636836ULL,},
         {  L_,      "1234567890123456",  9862342523424011374ULL,},
         {  L_,     "12345678901234567",  1788935288602307262ULL,},
         {  L_,    "123456789012345678",  4717428848732367803ULL,},
         {  L_,   "1234567890123456789", 17814078940325658812ULL,},
         {  L_,  "12345678901234567890", 10441832432953046058ULL,},
#endif
        };
        const int NUM_DATA = sizeof DATA / sizeof *DATA;

        if (verbose) printf("Insert various lengths of c-strings into the"
                            " algorithm both all at once and char by char"
                            " using 'operator()'.  Assert that the algorithm"
                            " produces the same result in both cases. (C-1,2)"
                            "\n");
        {
            for (int i = 0; i != NUM_DATA; ++i) {
                const int   LINE  = DATA[i].d_line;
                const char *VALUE = DATA[i].d_value;

                if (veryVerbose) printf("Hashing: %s\n", VALUE);

                Obj contiguousHash;
                Obj dispirateHash;

                contiguousHash(VALUE, strlen(VALUE));
                for (unsigned int j = 0; j < strlen(VALUE); ++j){
                    if (veryVeryVerbose) printf("Hashing by char: %c\n",
                                                                     VALUE[j]);
                    dispirateHash(&VALUE[j], sizeof(char));
                }

                LOOP_ASSERT(LINE, contiguousHash.computeHash() ==
                                                  dispirateHash.computeHash());
            }
        }

        if (verbose) printf("Hash c-strings all at once and with multiple"
                            " calls to 'operator()' with length 0.  Assert"
                            " that both methods of hashing c-strings produce"
                            " the same values.(C-3)\n");
        {
            for (int i = 0; i != NUM_DATA; ++i) {
                const int   LINE  = DATA[i].d_line;
                const char *VALUE = DATA[i].d_value;

                if (veryVerbose) printf("Hashing: %s\n", VALUE);

                Obj contiguousHash;
                Obj dispirateHash;

                contiguousHash(VALUE, strlen(VALUE));
                for (unsigned int j = 0; j < strlen(VALUE); ++j){
                    if (veryVeryVerbose) printf("Hashing by char: %c\n",
                                                                     VALUE[j]);
                    dispirateHash(&VALUE[j], sizeof(char));
                    dispirateHash(VALUE, 0);
                }

                LOOP_ASSERT(LINE, contiguousHash.computeHash() ==
                                                  dispirateHash.computeHash());
            }
        }

        if (verbose) printf("Check the output of 'computeHash()' against the"
                            " expected results from a known good version of"
                            " the algorithm. (C-4)\n");
        {
            for (int i = 0; i != NUM_DATA; ++i) {
                const int                LINE  = DATA[i].d_line;
                const char              *VALUE = DATA[i].d_value;
                const unsigned long long HASH  = DATA[i].d_expectedHash;

                if (veryVerbose) printf("Hashing: %s, Expecting: %llu\n",
                                        VALUE,
                                        HASH);

                Obj hash;
                hash(VALUE, strlen(VALUE));
                LOOP_ASSERT(LINE, hash.computeHash() == HASH);
            }
        }

        if (verbose) printf("Call 'operator()' with null pointers. (C-5)\n");
        {
            const char data[5] = {'a', 'b', 'c', 'd', 'e'};

            bsls::AssertTestHandlerGuard guard;

            ASSERT_FAIL(Obj().operator()(   0, 5));
            ASSERT_PASS(Obj().operator()(data, 5));
        }

      } break;
      case 2: {
        // --------------------------------------------------------------------
        // TESTING CREATORS
        //   Ensure that the implicit destructor as well as the explicit
        //   default and parameterized constructors are publicly callable.
        //   Verify that the algorithm can be instantiated with or without a
        //   seed.  Note that a null pointer is not tested here, because there
        //   is no way to perform a BSLS_ASSERT before dereferenceing the
        //   pointer (without a performance penalty).
        //
        // Concerns:
        //: 1 Objects can be created using the default constructor.
        //:
        //: 2 Objects can be created using the parameterized constructor.
        //:
        //: 3 Objects can be destroyed.
        //
        // Plan:
        //: 1 Create a default constructed 'SpookyHashAlgorithm' and allow it
        //:   to leave scope to be destroyed. (C-1,3)
        //:
        //: 2 Call the parameterized constructor with a seed. (C-2)
        //
        // Testing:
        //   SpookyHashAlgorithm();
        //   SpookyHashAlgorithm(const char *seed);
        //   ~SpookyHashAlgorithm();
        // --------------------------------------------------------------------

        if (verbose)
            printf("\nTESTING CREATORS"
                   "\n================\n");

        if (verbose) printf("Create a default constructed"
                            " 'SpookyHashAlgorithm' and allow it to leave"
                            " scope to be destroyed. (C-1,3)\n");
        {
            Obj alg1;
        }

        if (verbose) printf("Call the parameterized constructor with a seed."
                            " (C-2)\n");
        {
            Uint64 array[2] = {0,0};
            Obj alg1(reinterpret_cast<const char *>(array));
        }

      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST
        //   This case exercises (but does not fully test) basic functionality.
        //
        // Concerns:
        //: 1 The class is sufficiently functional to enable comprehensive
        //:   testing in subsequent test cases.
        //
        // Plan:
        //: 1 Create an instance of 'bsl::SpookyHashAlgorithm'. (C-1)
        //:
        //: 2 Verify different hashes are produced for different c-strings.
        //:   (C-1)
        //:
        //: 3 Verify the same hashes are produced for the same c-strings. (C-1)
        //:
        //: 4 Verify different hashes are produced for different 'int's. (C-1)
        //:
        //: 5 Verify the same hashes are produced for the same 'int's. (C-1)
        //
        // Testing:
        //   BREATHING TEST
        // --------------------------------------------------------------------

        if (verbose) printf("\nBREATHING TEST"
                            "\n==============\n");

        if (verbose) printf("Instantiate 'bsl::SpookyHashAlgorithm'\n");
        {
            SpookyHashAlgorithm hashAlg;
        }

        if (verbose) printf("Verify different hashes are produced for"
                            " different c-strings.\n");
        {
            SpookyHashAlgorithm hashAlg1;
            SpookyHashAlgorithm hashAlg2;
            const char * str1 = "Hello World";
            const char * str2 = "Goodbye World";
            hashAlg1(str1, strlen(str1));
            hashAlg2(str2, strlen(str2));
            ASSERT(hashAlg1.computeHash() != hashAlg2.computeHash());
        }

        if (verbose) printf("Verify the same hashes are produced for the same"
                            " c-strings.\n");
        {
            SpookyHashAlgorithm hashAlg1;
            SpookyHashAlgorithm hashAlg2;
            const char * str1 = "Hello World";
            const char * str2 = "Hello World";
            hashAlg1(str1, strlen(str1));
            hashAlg2(str2, strlen(str2));
            ASSERT(hashAlg1.computeHash() == hashAlg2.computeHash());
        }

        if (verbose) printf("Verify different hashes are produced for"
                            " different 'int's.\n");
        {
            SpookyHashAlgorithm hashAlg1;
            SpookyHashAlgorithm hashAlg2;
            int int1 = 123456;
            int int2 = 654321;
            hashAlg1(&int1, sizeof(int));
            hashAlg2(&int2, sizeof(int));
            ASSERT(hashAlg1.computeHash() != hashAlg2.computeHash());
        }

        if (verbose) printf("Verify the same hashes are produced for the same"
                            " 'int's.\n");
        {
            SpookyHashAlgorithm hashAlg1;
            SpookyHashAlgorithm hashAlg2;
            int int1 = 123456;
            int int2 = 123456;
            hashAlg1(&int1, sizeof(int));
            hashAlg2(&int2, sizeof(int));
            ASSERT(hashAlg1.computeHash() == hashAlg2.computeHash());
        }
      } break;
      default: {
        fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test);
        testStatus = -1;
      }
    }
    return testStatus;
}
int main(int argc, char *argv[])
{
    int                 test = argc > 1 ? atoi(argv[1]) : 0;
    bool             verbose = argc > 2;
    bool         veryVerbose = argc > 3;
    bool     veryVeryVerbose = argc > 4;
//  bool veryVeryVeryVerbose = argc > 5;

    printf("TEST " __FILE__ " CASE %d\n", test);

    switch (test) { case 0:
      case 5: {
        // --------------------------------------------------------------------
        // USAGE EXAMPLE
        //   The hashing algorithm can be used to create more powerful
        //   components such as functors that can be used to power hash tables.
        //
        // Concerns:
        //: 1 The usage example provided in the component header file compiles,
        //:   links, and runs as shown.
        //
        // Plan:
        //: 1 Incorporate usage example from header into test driver (C-1)
        //
        // Testing:
        //   USAGE EXAMPLE
        // --------------------------------------------------------------------

        if (verbose) printf("USAGE EXAMPLE\n"
                            "=============\n");

// Then, we want to actually use our hash table on 'Future' objects.  We
// create an array of 'Future's based on data that was originally from some
// external source:

        Future futures[] = { Future("Swiss Franc", 'F', 2014),
                             Future("US Dollar", 'G', 2015),
                             Future("Canadian Dollar", 'Z', 2014),
                             Future("British Pound", 'M', 2015),
                             Future("Deutsche Mark", 'X', 2016),
                             Future("Eurodollar", 'Q', 2017)};
        enum { NUM_FUTURES = sizeof futures / sizeof *futures };

// Next, we create our HashTable 'hashTable'.  We pass the functor that we
// defined above as the second argument:

        HashTable<Future, HashFuture> hashTable(futures, NUM_FUTURES);

// Now, we verify that each element in our array registers with count:
        for ( int i = 0; i < 6; ++i) {
            ASSERT(hashTable.contains(futures[i]));
        }

// Finally, we verify that futures not in our original array are correctly
// identified as not being in the set:

        ASSERT(!hashTable.contains(Future("French Franc", 'N', 2019)));
        ASSERT(!hashTable.contains(Future("Swiss Franc", 'X', 2014)));
        ASSERT(!hashTable.contains(Future("US Dollar", 'F', 2014)));

      } break;
      case 4: {
        // --------------------------------------------------------------------
        // TESTING 'result_type' TYPEDEF
        //   Verify that the class offers the result_type typedef that needs to
        //   be exposed by all 'bslh' hashing algorithms
        //
        // Concerns:
        //: 1 The typedef 'result_type' is publicly accessible and an alias for
        //:   'bslh::SpookyHashAlgorithm::result_type'.
        //:
        //: 2 'computeHash()' returns 'result_type'
        //
        // Plan:
        //: 1 ASSERT the typedef is accessible and is the correct type using
        //:   'bslmf::IsSame'. (C-1)
        //:
        //: 2 Declare the expected signature of 'computeHash()' and then assign
        //:   to it.  If it compiles, the test passes. (C-2)
        //
        // Testing:
        //   typedef InternalHashAlgorithm::result_type result_type;
        // --------------------------------------------------------------------

        if (verbose) printf("\nTESTING 'result_type' TYPEDEF"
                            "\n=============================\n");

        if (verbose) printf("ASSERT the typedef is accessible and is the"
                            " correct type using 'bslmf::IsSame'. (C-1)\n");
        {
            ASSERT((bslmf::IsSame<Obj::result_type,
                                  SpookyHashAlgorithm::result_type>::VALUE));
        }

        if (verbose) printf("Declare the expected signature of 'computeHash()'"
                            " and then assign to it.  If it compiles, the test"
                            " passes. (C-2)\n");
        {
            Obj::result_type (Obj::*expectedSignature) ();

            expectedSignature = &Obj::computeHash;
        }

      } break;
      case 3: {
        // --------------------------------------------------------------------
        // TESTING 'operator()' AND 'computeHash()'
        //   Verify the class provides an overload for the function call
        //   operator that can be called with some bytes and a length.  Verify
        //   that calling 'operator()' will permute the algorithm's internal
        //   state as specified by the underlying hashing algorithm
        //   (bslh::SpookyHashAlgorithm).  Verify that 'computeHash()' returns
        //   the final value specified by the canonical implementation of the
        //   underlying hashing algorithm.
        //
        // Concerns:
        //: 1 The function call operator is callable.
        //:
        //: 2 The 'computeHash()' function is callable.
        //:
        //: 3 The output of calling 'operator()' and then 'computeHash()'
        //:   matches the output of the underlying hashing algorithm.
        //:
        //: 4 'operator()' does a BSLS_ASSERT for null pointers.
        //
        // Plan:
        //: 1 Hash a number of values with 'bslh::DefaultHashAlgorithm' and
        //:   'bslh::SpookyHashAlgorithm' and verify that the outputs match.
        //:   (C-1,2,3)
        //:
        //: 2 Call 'operator()' with a null pointer. (C-4)
        //
        // Testing:
        //   void operator()(void const* key, size_t len);
        //   result_type computeHash();
        // --------------------------------------------------------------------

        if (verbose) printf(
                       "\nTESTING 'operator()' AND 'computeHash()'"
                       "\n========================================\n");

        static const struct {
            int                  d_line;
            const char           d_value [21];
        } DATA[] = {
           // LINE           DATA
            {  L_,                     "1",},
            {  L_,                    "12",},
            {  L_,                   "123",},
            {  L_,                  "1234",},
            {  L_,                 "12345",},
            {  L_,                "123456",},
            {  L_,               "1234567",},
            {  L_,              "12345678",},
            {  L_,             "123456789",},
            {  L_,            "1234567890",},
            {  L_,           "12345678901",},
            {  L_,          "123456789012",},
            {  L_,         "1234567890123",},
            {  L_,        "12345678901234",},
            {  L_,       "123456789012345",},
            {  L_,      "1234567890123456",},
            {  L_,     "12345678901234567",},
            {  L_,    "123456789012345678",},
            {  L_,   "1234567890123456789",},
            {  L_,  "12345678901234567890",},
        };
        const int NUM_DATA = sizeof DATA / sizeof *DATA;

        if (verbose) printf("Hash a number of values with"
                            " 'bslh::DefaultHashAlgorithm' and"
                            " 'bslh::SpookyHashAlgorithm' and verify that the"
                            " outputs match. (C-1,2,3)\n");
        {
            for (int i = 0; i != NUM_DATA; ++i) {
                const int   LINE  = DATA[i].d_line;
                const char *VALUE = DATA[i].d_value;

                if (veryVerbose) printf("Hashing: %s\n with"
                                        " 'bslh::DefaultHashAlgorithm' and"
                                        " 'bslh::SpookyHashAlgorithm'", VALUE);

                Obj                 contiguousHash;
                Obj                 dispirateHash;
                SpookyHashAlgorithm cannonicalHashAlgorithm;

                cannonicalHashAlgorithm(VALUE, strlen(VALUE));
                contiguousHash(VALUE, strlen(VALUE));

                for (unsigned int j = 0; j < strlen(VALUE); ++j){
                    if (veryVeryVerbose) printf("Hashing by char: %c\n",
                                                                     VALUE[j]);
                    dispirateHash(&VALUE[j], sizeof(char));
                }

                SpookyHashAlgorithm::result_type hash =
                                         cannonicalHashAlgorithm.computeHash();

                LOOP_ASSERT(LINE, hash == contiguousHash.computeHash());
                LOOP_ASSERT(LINE, hash == dispirateHash.computeHash());
            }
        }

        if (verbose) printf("Call 'operator()' with null pointers. (C-4)\n");
        {
            const char data[5] = {'a', 'b', 'c', 'd', 'e'};

            bsls::AssertFailureHandlerGuard
                                           g(bsls::AssertTest::failTestDriver);

            ASSERT_FAIL(Obj()(   0, 5));
            ASSERT_PASS(Obj()(data, 5));
        }

      } break;
      case 2: {
        // --------------------------------------------------------------------
        // TESTING CREATORS
        //   Ensure that the implicit destructor and the explicit default
        //   constructor are publicly callable.
        //
        // Concerns:
        //: 1 Objects can be created using the parameterized constructor.
        //:
        //: 2 Objects can be destroyed.
        //
        // Plan:
        //: 1 Create a default constructed 'DefaultHashAlgorithm' and allow it
        //:   to leave scope to be destroyed. (C-1,2)
        //
        // Testing:
        //   DefaultHashAlgorithm();
        //   ~DefaultHashAlgorithm();
        // --------------------------------------------------------------------

        if (verbose)
            printf("\nTESTING CREATORS"
                   "\n================\n");

        if (verbose) printf("Create a default constructed"
                            " 'DefaultHashAlgorithm' and allow it to leave"
                            " scope to be destroyed. (C-1,2)\n");
        {
            Obj alg1;
        }

      } break;
      case 1: {
        // --------------------------------------------------------------------
        // BREATHING TEST
        //   This case exercises (but does not fully test) basic functionality.
        //
        // Concerns:
        //: 1 The class is sufficiently functional to enable comprehensive
        //:   testing in subsequent test cases.
        //
        // Plan:
        //: 1 Create an instance of 'bsl::DefaultHashAlgorithm'. (C-1)
        //:
        //: 2 Verify different hashes are produced for different c-strings.
        //:   (C-1)
        //:
        //: 3 Verify the same hashes are produced for the same c-strings. (C-1)
        //:
        //: 4 Verify different hashes are produced for different 'int's. (C-1)
        //:
        //: 5 Verify the same hashes are produced for the same 'int's. (C-1)
        //
        // Testing:
        //   BREATHING TEST
        // --------------------------------------------------------------------

        if (verbose) printf("\nBREATHING TEST"
                            "\n==============\n");

        if (verbose) printf("Instantiate 'bsl::DefaultHashAlgorithm'\n");
        {
            Obj hashAlg;
        }

        if (verbose) printf("Verify different hashes are produced for"
                            " different c-strings.\n");
        {
            Obj hashAlg1;
            Obj hashAlg2;
            const char * str1 = "Hello World";
            const char * str2 = "Goodbye World";
            hashAlg1(str1, strlen(str1));
            hashAlg2(str2, strlen(str2));
            ASSERT(hashAlg1.computeHash() != hashAlg2.computeHash());
        }

        if (verbose) printf("Verify the same hashes are produced for the same"
                            " c-strings.\n");
        {
            Obj hashAlg1;
            Obj hashAlg2;
            const char * str1 = "Hello World";
            const char * str2 = "Hello World";
            hashAlg1(str1, strlen(str1));
            hashAlg2(str2, strlen(str2));
            ASSERT(hashAlg1.computeHash() == hashAlg2.computeHash());
        }

        if (verbose) printf("Verify different hashes are produced for"
                            " different 'int's.\n");
        {
            Obj hashAlg1;
            Obj hashAlg2;
            int int1 = 123456;
            int int2 = 654321;
            hashAlg1(&int1, sizeof(int));
            hashAlg2(&int2, sizeof(int));
            ASSERT(hashAlg1.computeHash() != hashAlg2.computeHash());
        }

        if (verbose) printf("Verify the same hashes are produced for the same"
                            " 'int's.\n");
        {
            Obj hashAlg1;
            Obj hashAlg2;
            int int1 = 123456;
            int int2 = 123456;
            hashAlg1(&int1, sizeof(int));
            hashAlg2(&int2, sizeof(int));
            ASSERT(hashAlg1.computeHash() == hashAlg2.computeHash());
        }
      } break;

      default: {
        fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test);
        testStatus = -1;
      }
    }

    if (testStatus > 0) {
        fprintf(stderr, "Error, non-zero test status = %d.\n", testStatus);
    }

    return testStatus;
}