Example #1
0
        size_t operator()(const Future& future) const
            // Return the hash of the of the specified 'future'.  Note that
            // this uses the 'SpookyHashAlgorithm' to quickly combine the
            // attributes of 'Future' objects that are salient to hashing into
            // a hash suitable for a hash table.
        {
            SpookyHashAlgorithm hash;

            hash(future.getName(),  strlen(future.getName()));
            hash(future.getMonth(), sizeof(char));
            hash(future.getYear(),  sizeof(short));

            return static_cast<size_t>(hash.computeHash());
        }
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;
}