Blame unit-tests/HTTPCacheTest.cc

Packit a4aae4
// -*- mode: c++; c-basic-offset:4 -*-
Packit a4aae4
Packit a4aae4
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
Packit a4aae4
// Access Protocol.
Packit a4aae4
Packit a4aae4
// Copyright (c) 2002,2003 OPeNDAP, Inc.
Packit a4aae4
// Author: James Gallagher <jgallagher@opendap.org>
Packit a4aae4
//
Packit a4aae4
// This library is free software; you can redistribute it and/or
Packit a4aae4
// modify it under the terms of the GNU Lesser General Public
Packit a4aae4
// License as published by the Free Software Foundation; either
Packit a4aae4
// version 2.1 of the License, or (at your option) any later version.
Packit a4aae4
//
Packit a4aae4
// This library is distributed in the hope that it will be useful,
Packit a4aae4
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a4aae4
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a4aae4
// Lesser General Public License for more details.
Packit a4aae4
//
Packit a4aae4
// You should have received a copy of the GNU Lesser General Public
Packit a4aae4
// License along with this library; if not, write to the Free Software
Packit a4aae4
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit a4aae4
//
Packit a4aae4
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
Packit a4aae4
Packit a4aae4
#include <unistd.h>   // for access stat
Packit a4aae4
#include <sys/types.h>
Packit a4aae4
#include <sys/stat.h>
Packit a4aae4
Packit a4aae4
#include <cstdio>     // for create_cache_root_test
Packit a4aae4
#include <string>
Packit a4aae4
#include <vector>
Packit a4aae4
#include <algorithm>
Packit a4aae4
#include <memory>
Packit a4aae4
#include <iterator>
Packit a4aae4
Packit a4aae4
#include <cppunit/TextTestRunner.h>
Packit a4aae4
#include <cppunit/extensions/TestFactoryRegistry.h>
Packit a4aae4
#include <cppunit/extensions/HelperMacros.h>
Packit a4aae4
Packit a4aae4
#include "HTTPCache.h"
Packit a4aae4
#include "HTTPConnect.h"	// Used to generate a response to cache.
Packit a4aae4
#ifndef WIN32			// Signals are exquisitely non-portable.
Packit a4aae4
#include "SignalHandler.h"	// Needed to clean up this singleton.
Packit a4aae4
#endif
Packit a4aae4
#include "RCReader.h"		// ditto
Packit a4aae4
#include"GetOpt.h"
Packit a4aae4
Packit a4aae4
// #define DODS_DEBUG
Packit a4aae4
Packit a4aae4
#include "debug.h"
Packit a4aae4
Packit a4aae4
#if defined(DODS_DEBUG) || defined(DODS_DEBUG2)
Packit a4aae4
#include <iterator>
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
using namespace CppUnit;
Packit a4aae4
using namespace std;
Packit a4aae4
Packit a4aae4
#ifdef WIN32
Packit a4aae4
#define F_OK 0
Packit a4aae4
#define W_OK 2
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
static bool debug = false;
Packit a4aae4
Packit a4aae4
#undef DBG
Packit a4aae4
#define DBG(x) do { if (debug) (x); } while(false);
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
inline static int file_size(string name)
Packit a4aae4
{
Packit a4aae4
    struct stat s;
Packit a4aae4
    stat(name.c_str(), &s);
Packit a4aae4
    return s.st_size;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
inline static void
Packit a4aae4
print_entry(HTTPCache *, HTTPCacheTable::CacheEntry **e)
Packit a4aae4
{
Packit a4aae4
    cerr << "Entry: " << (*e)->get_cachename() << endl;
Packit a4aae4
}
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
// Note that because this test class uses the fixture 'hc' we must always
Packit a4aae4
// force access to the single user/process lock for the cache. This is
Packit a4aae4
// because a fixture is always created (by setUp) *before* the body of the
Packit a4aae4
// test is run. So by the time we're at the first line of the test, The
Packit a4aae4
// persistent store's lock has already been grabbed. 10/14/02 jhrg
Packit a4aae4
Packit a4aae4
class HTTPCacheTest: public TestFixture {
Packit a4aae4
private:
Packit a4aae4
    HTTPCache *hc;
Packit a4aae4
    HTTPConnect *http_conn;
Packit a4aae4
    string index_file_line;
Packit a4aae4
    string localhost_url;
Packit a4aae4
    string expired;
Packit a4aae4
    int hash_value;
Packit a4aae4
    vector<string> h;
Packit a4aae4
Packit a4aae4
protected:
Packit a4aae4
Packit a4aae4
public:
Packit a4aae4
    HTTPCacheTest() :
Packit a4aae4
        hc(0), http_conn(0)
Packit a4aae4
    {
Packit a4aae4
        putenv((char*) "DODS_CONF=./cache-testsuite/dodsrc");
Packit a4aae4
        http_conn = new HTTPConnect(RCReader::instance());
Packit a4aae4
Packit a4aae4
        DBG2(cerr << "Entering HTTPCacheTest ctor... ");
Packit a4aae4
        hash_value = 656;
Packit a4aae4
        localhost_url = "http://test.opendap.org/test-304.html";
Packit a4aae4
        index_file_line =
Packit a4aae4
            "http://test.opendap.org/test-304.html cache-testsuite/dods_cache/656/dodsKbcD0h \"3f62c-157-139c2680\" 1121283146 -1 343 0 656 1 7351 1121360379 3723 0";
Packit a4aae4
Packit a4aae4
        expired = "http://test.opendap.org/cgi-bin/expires.sh";
Packit a4aae4
Packit a4aae4
        h.push_back("ETag: jhrgjhrgjhrg");
Packit a4aae4
        h.push_back("Last-Modified: Sat, 05 Nov 1994 08:49:37 GMT");
Packit a4aae4
        h.push_back("Expires: Mon, 07 Nov 1994 08:49:37 GMT");
Packit a4aae4
        h.push_back("Date: Sun, 06 Nov 1994 08:49:37 GMT");
Packit a4aae4
        DBG2(cerr << "exiting." << endl);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    ~HTTPCacheTest()
Packit a4aae4
    {
Packit a4aae4
        delete http_conn;
Packit a4aae4
        http_conn = 0;
Packit a4aae4
        DBG2(cerr << "Entering the HTTPCacheTest dtor... ");DBG2(cerr << "exiting." << endl);
Packit a4aae4
    }
Packit a4aae4
#if 0
Packit a4aae4
    static inline bool
Packit a4aae4
    is_hop_by_hop_header(const string &header) {
Packit a4aae4
        return header.find("Connection") != string::npos
Packit a4aae4
        || header.find("Keep-Alive") != string::npos
Packit a4aae4
        || header.find("Proxy-Authenticate") != string::npos
Packit a4aae4
        || header.find("Proxy-Authorization") != string::npos
Packit a4aae4
        || header.find("Transfer-Encoding") != string::npos
Packit a4aae4
        || header.find("Upgrade") != string::npos;
Packit a4aae4
    }
Packit a4aae4
#endif
Packit a4aae4
    void setUp()
Packit a4aae4
    {
Packit a4aae4
        // Called before every test.
Packit a4aae4
        DBG2(cerr << "Entering HTTPCacheTest::setUp... " << endl);
Packit a4aae4
        hc = new HTTPCache("cache-testsuite/dods_cache/", true);
Packit a4aae4
        DBG2(cerr << "exiting setUp" << endl);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void tearDown()
Packit a4aae4
    {
Packit a4aae4
        // Called after every test.
Packit a4aae4
        DBG2(cerr << "Entering HTTPCacheTest::tearDown... " << endl);
Packit a4aae4
        delete hc;
Packit a4aae4
        hc = 0;
Packit a4aae4
        DBG2(cerr << "exiting tearDown" << endl);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST_SUITE (HTTPCacheTest);
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST (constructor_test);
Packit a4aae4
    CPPUNIT_TEST (cache_index_read_test);
Packit a4aae4
    CPPUNIT_TEST (cache_index_parse_line_test);
Packit a4aae4
    CPPUNIT_TEST (get_entry_from_cache_table_test);
Packit a4aae4
    CPPUNIT_TEST (cache_index_write_test);
Packit a4aae4
    CPPUNIT_TEST (create_cache_root_test);
Packit a4aae4
    CPPUNIT_TEST (set_cache_root_test);
Packit a4aae4
    CPPUNIT_TEST (get_single_user_lock_test);
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST (release_single_user_lock_test);
Packit a4aae4
    CPPUNIT_TEST (create_hash_directory_test);
Packit a4aae4
    CPPUNIT_TEST (create_location_test);
Packit a4aae4
    CPPUNIT_TEST (parse_headers_test);
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST (calculate_time_test);
Packit a4aae4
    CPPUNIT_TEST (write_metadata_test);
Packit a4aae4
    CPPUNIT_TEST (cache_response_test);
Packit a4aae4
#if 0
Packit a4aae4
    // This test does not seem to work in New Zealand - maybe because
Packit a4aae4
    // of the dateline??? jhrg 1/31/13
Packit a4aae4
    CPPUNIT_TEST(is_url_valid_test);
Packit a4aae4
#endif
Packit a4aae4
    CPPUNIT_TEST (get_cached_response_test);
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST (perform_garbage_collection_test);
Packit a4aae4
    CPPUNIT_TEST (purge_cache_and_release_cached_response_test);
Packit a4aae4
    CPPUNIT_TEST (get_conditional_response_headers_test);
Packit a4aae4
    CPPUNIT_TEST (update_response_test);
Packit a4aae4
    CPPUNIT_TEST (cache_gc_test);
Packit a4aae4
Packit a4aae4
    // Make this the last test because when distcheck is run, running
Packit a4aae4
    // it before other tests will break them.
Packit a4aae4
    CPPUNIT_TEST (instance_test);
Packit a4aae4
Packit a4aae4
    CPPUNIT_TEST_SUITE_END();
Packit a4aae4
Packit a4aae4
    void constructor_test()
Packit a4aae4
    {
Packit a4aae4
        DBG(cerr << "hc->cache_index: " << hc->d_http_cache_table->d_cache_index << endl);
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_http_cache_table->d_cache_index == "cache-testsuite/dods_cache/.index");
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_cache_root == "cache-testsuite/dods_cache/");
Packit a4aae4
        DBG(cerr << "Current size: " << hc->d_http_cache_table->d_current_size << endl);
Packit a4aae4
        DBG(cerr << "Block size: " << hc->d_http_cache_table->d_block_size << endl);
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_http_cache_table->d_current_size == hc->d_http_cache_table->d_block_size);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void cache_index_read_test()
Packit a4aae4
    {
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_http_cache_table->cache_index_read());
Packit a4aae4
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = hc->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(e);
Packit a4aae4
        CPPUNIT_ASSERT(e->url == localhost_url);
Packit a4aae4
        e->unlock_read_response();
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void cache_index_parse_line_test()
Packit a4aae4
    {
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = hc->d_http_cache_table->cache_index_parse_line(index_file_line.c_str());
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(e->url == localhost_url);
Packit a4aae4
        CPPUNIT_ASSERT(e->cachename == "cache-testsuite/dods_cache/656/dodsKbcD0h");
Packit a4aae4
#ifdef WIN32
Packit a4aae4
        char *tmpstr = "\"3f62c-157-139c2680\"";
Packit a4aae4
        CPPUNIT_ASSERT(e->etag == tmpstr);
Packit a4aae4
#else
Packit a4aae4
        CPPUNIT_ASSERT(e->etag == "\"3f62c-157-139c2680\"");
Packit a4aae4
#endif
Packit a4aae4
        CPPUNIT_ASSERT(e->lm == 1121283146);
Packit a4aae4
        // Skip ahead ...
Packit a4aae4
        CPPUNIT_ASSERT(e->must_revalidate == false);
Packit a4aae4
Packit a4aae4
        delete e;
Packit a4aae4
        e = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // This will also test the add_entry_to_cache_table() method.
Packit a4aae4
    void get_entry_from_cache_table_test()
Packit a4aae4
    {
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = hc->d_http_cache_table->cache_index_parse_line(index_file_line.c_str());
Packit a4aae4
Packit a4aae4
        // Test adding an entry and getting it back.
Packit a4aae4
        hc->d_http_cache_table->add_entry_to_cache_table(e);
Packit a4aae4
Packit a4aae4
        HTTPCacheTable::CacheEntry *e2 = hc->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
        CPPUNIT_ASSERT(e2);
Packit a4aae4
        CPPUNIT_ASSERT(e2->url == localhost_url);
Packit a4aae4
        e2->unlock_read_response();
Packit a4aae4
Packit a4aae4
        // Now test what happens when two entries collide.
Packit a4aae4
        HTTPCacheTable::CacheEntry *e3 = hc->d_http_cache_table->cache_index_parse_line(index_file_line.c_str());
Packit a4aae4
Packit a4aae4
        // Change the url so we can tell the difference (the hash is the same)
Packit a4aae4
        e3->url = "http://new.url.same.hash/test/collisions.gif";
Packit a4aae4
Packit a4aae4
        hc->d_http_cache_table->add_entry_to_cache_table(e3);
Packit a4aae4
Packit a4aae4
        // Use the version of get_entry... that lets us pass in the hash
Packit a4aae4
        // value (as opposed to the normal version which calculates the hash
Packit a4aae4
        // from the url. 10/01/02 jhrg
Packit a4aae4
        HTTPCacheTable::CacheEntry *g = hc->d_http_cache_table->get_locked_entry_from_cache_table(hash_value, e3->url);
Packit a4aae4
        CPPUNIT_ASSERT(g);
Packit a4aae4
        CPPUNIT_ASSERT(g->url == e3->url);
Packit a4aae4
        g->unlock_read_response();
Packit a4aae4
Packit a4aae4
        g = hc->d_http_cache_table->get_locked_entry_from_cache_table("http://not.in.table/never.x");
Packit a4aae4
        CPPUNIT_ASSERT(g == 0);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void cache_index_write_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            HTTPCache * hc_3 = new HTTPCache("cache-testsuite/dods_cache/", true);
Packit a4aae4
            hc_3->d_http_cache_table->add_entry_to_cache_table(
Packit a4aae4
                hc->d_http_cache_table->cache_index_parse_line(index_file_line.c_str()));
Packit a4aae4
Packit a4aae4
            hc_3->d_http_cache_table->d_cache_index = hc->d_cache_root + "test_index";
Packit a4aae4
            hc_3->d_http_cache_table->cache_index_write();
Packit a4aae4
Packit a4aae4
            HTTPCache *hc_4 = new HTTPCache("cache-testsuite/dods_cache/", true);
Packit a4aae4
            hc_4->d_http_cache_table->d_cache_index = hc_3->d_cache_root + "test_index";
Packit a4aae4
            hc_4->d_http_cache_table->cache_index_read();
Packit a4aae4
Packit a4aae4
            HTTPCacheTable::CacheEntry *e = hc_4->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
            DBG(cerr << "Got locked entry" << endl);
Packit a4aae4
            CPPUNIT_ASSERT(e);
Packit a4aae4
            CPPUNIT_ASSERT(e->url == localhost_url);
Packit a4aae4
            e->unlock_read_response();
Packit a4aae4
Packit a4aae4
            delete hc_3;
Packit a4aae4
            hc_3 = 0;
Packit a4aae4
            delete hc_4;
Packit a4aae4
            hc_4 = 0;
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            //cerr << "Fail: " << e.get_error_message() << endl;
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void create_cache_root_test()
Packit a4aae4
    {
Packit a4aae4
        hc->create_cache_root("/tmp/silly/");
Packit a4aae4
        CPPUNIT_ASSERT(access("/tmp/silly/", F_OK) == 0);
Packit a4aae4
        remove("/tmp/silly");
Packit a4aae4
#if 0
Packit a4aae4
        // This test doesn't work on some machines where the build is
Packit a4aae4
        // run as root or where /root is owned by some other user (as is
Packit a4aae4
        // the case with OS/X.
Packit a4aae4
        try {
Packit a4aae4
            hc->create_cache_root("/root/very_silly/");
Packit a4aae4
            access("/root/very_silly/", F_OK);
Packit a4aae4
            remove("/root/very_silly/");
Packit a4aae4
            CPPUNIT_ASSERT(!"Should not be able to do this...");
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_ASSERT("This is where we want to be");
Packit a4aae4
            CPPUNIT_ASSERT(access("/root/very_silly/", F_OK) != 0);
Packit a4aae4
        }
Packit a4aae4
#endif
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void set_cache_root_test()
Packit a4aae4
    {
Packit a4aae4
#if 0
Packit a4aae4
        // env var support removed 3/22/11 jhrg
Packit a4aae4
        putenv("DODS_CACHE=/home/jimg");
Packit a4aae4
        hc->set_cache_root();
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_cache_root == "/home/jimg/dods-cache/");
Packit a4aae4
        remove("/home/jimg/w3c-cache/");
Packit a4aae4
#endif
Packit a4aae4
        hc->set_cache_root("/home/jimg/test_cache");
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_cache_root == "/home/jimg/test_cache/");
Packit a4aae4
        remove("/home/jimg/test_cache/");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void get_single_user_lock_test()
Packit a4aae4
    {
Packit a4aae4
        hc->set_cache_root("/tmp/dods_test_cache");
Packit a4aae4
        hc->release_single_user_lock();
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(hc->get_single_user_lock());
Packit a4aae4
        CPPUNIT_ASSERT(access("/tmp/dods_test_cache/.lock", F_OK) == 0);
Packit a4aae4
Packit a4aae4
        // Second time should fail
Packit a4aae4
        CPPUNIT_ASSERT(!hc->get_single_user_lock());
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void release_single_user_lock_test()
Packit a4aae4
    {
Packit a4aae4
        hc->set_cache_root("/tmp/dods_test_cache");
Packit a4aae4
        remove("/tmp/dods_test_cache/.lock"); // in case prev. test fails
Packit a4aae4
        hc->d_locked_open_file = 0;
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(hc->get_single_user_lock());
Packit a4aae4
        CPPUNIT_ASSERT(access("/tmp/dods_test_cache/.lock", F_OK) == 0);
Packit a4aae4
Packit a4aae4
        hc->release_single_user_lock();
Packit a4aae4
        CPPUNIT_ASSERT(hc->get_single_user_lock());
Packit a4aae4
        CPPUNIT_ASSERT(access("/tmp/dods_test_cache/.lock", F_OK) == 0);
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(!hc->get_single_user_lock());
Packit a4aae4
Packit a4aae4
        remove("/tmp/dods_test_cache/.lock");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void create_hash_directory_test()
Packit a4aae4
    {
Packit a4aae4
        hc->set_cache_root("/tmp/dods_test_cache");
Packit a4aae4
        CPPUNIT_ASSERT(hc->d_http_cache_table->create_hash_directory(391) == "/tmp/dods_test_cache/391");
Packit a4aae4
        CPPUNIT_ASSERT(access("/tmp/dods_test_cache/391", W_OK) == 0);
Packit a4aae4
#if 0
Packit a4aae4
        // This test doesn't work on some machines where the build is
Packit a4aae4
        // run as root or where /root is owned by some other user (as is
Packit a4aae4
        // the case with OS/X.
Packit a4aae4
        hc->set_cache_root("/root/");
Packit a4aae4
        try {
Packit a4aae4
            hc->create_hash_directory(391);
Packit a4aae4
            CPPUNIT_ASSERT(!"Create in bad directory");
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
        }
Packit a4aae4
#endif
Packit a4aae4
        remove("/tmp/dods_test_cache/391");
Packit a4aae4
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void create_location_test()
Packit a4aae4
    {
Packit a4aae4
        hc->set_cache_root("/tmp/dods_test_cache");
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = new HTTPCacheTable::CacheEntry;
Packit a4aae4
        e->url = localhost_url;
Packit a4aae4
        e->hash = hash_value;
Packit a4aae4
        try {
Packit a4aae4
            hc->d_http_cache_table->create_location(e);
Packit a4aae4
            CPPUNIT_ASSERT(e->cachename != "");
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_ASSERT(true && "could not create entry file");
Packit a4aae4
        }
Packit a4aae4
        remove(e->cachename.c_str());
Packit a4aae4
Packit a4aae4
        delete e;
Packit a4aae4
        e = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void parse_headers_test()
Packit a4aae4
    {
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = new HTTPCacheTable::CacheEntry;
Packit a4aae4
Packit a4aae4
        hc->d_http_cache_table->parse_headers(e, hc->d_max_entry_size, h);
Packit a4aae4
        CPPUNIT_ASSERT(e->lm == 784025377);
Packit a4aae4
Packit a4aae4
        delete e;
Packit a4aae4
        e = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void calculate_time_test()
Packit a4aae4
    {
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = new HTTPCacheTable::CacheEntry;
Packit a4aae4
Packit a4aae4
        hc->d_http_cache_table->parse_headers(e, hc->d_max_entry_size, h);
Packit a4aae4
        hc->d_http_cache_table->calculate_time(e, hc->d_default_expiration, time(0));
Packit a4aae4
        CPPUNIT_ASSERT(e->corrected_initial_age > 249300571);
Packit a4aae4
        CPPUNIT_ASSERT(e->freshness_lifetime == 86400);
Packit a4aae4
Packit a4aae4
        delete e;
Packit a4aae4
        e = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void write_metadata_test()
Packit a4aae4
    {
Packit a4aae4
        hc->set_cache_root("/tmp/dods_test_cache");
Packit a4aae4
        HTTPCacheTable::CacheEntry *e = new HTTPCacheTable::CacheEntry;
Packit a4aae4
        try {
Packit a4aae4
            e->hash = 101;
Packit a4aae4
            hc->d_http_cache_table->create_location(e);
Packit a4aae4
            CPPUNIT_ASSERT(e->cachename != "");
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_ASSERT(true && "could not create entry file");
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        hc->write_metadata(e->cachename, h);
Packit a4aae4
        vector<string> headers;
Packit a4aae4
        hc->read_metadata(e->cachename, headers);
Packit a4aae4
Packit a4aae4
        vector<string>::iterator i, j;
Packit a4aae4
        for (i = headers.begin(), j = h.begin(); i != headers.end() && j != h.end(); ++i, ++j) {
Packit a4aae4
            CPPUNIT_ASSERT(*i == *j);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        remove(e->cachename.c_str());
Packit a4aae4
        remove(string(e->cachename + ".meta").c_str());
Packit a4aae4
        delete e;
Packit a4aae4
        e = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void cache_response_test()
Packit a4aae4
    {
Packit a4aae4
        HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
        try {
Packit a4aae4
            time_t now = time(0);
Packit a4aae4
            vector<string> *headers = rs->get_headers();
Packit a4aae4
            hc->cache_response(localhost_url, now, *headers, rs->get_stream());
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(hc->is_url_in_cache(localhost_url));
Packit a4aae4
Packit a4aae4
            HTTPCacheTable::CacheEntry *e = hc->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
            CPPUNIT_ASSERT(file_size(e->cachename) == 343);
Packit a4aae4
            e->unlock_read_response();
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
            cerr << "Error: " << e.get_error_message() << endl;
Packit a4aae4
            CPPUNIT_ASSERT(!"Caught unexpected Error/InternalErr");
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void is_url_valid_test()
Packit a4aae4
    {
Packit a4aae4
        cache_response_test(); // This should get a response into the cache.
Packit a4aae4
        CPPUNIT_ASSERT(hc->is_url_valid(localhost_url));
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void get_cached_response_test()
Packit a4aae4
    {
Packit a4aae4
        cache_response_test(); // Get a response into the cache.
Packit a4aae4
        vector<string> cached_headers;
Packit a4aae4
        FILE *cached_body = hc->get_cached_response(localhost_url, cached_headers);
Packit a4aae4
Packit a4aae4
        HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
        vector<string> *headers = rs->get_headers();
Packit a4aae4
Packit a4aae4
        // headers and cached_headers should match, except for the values.
Packit a4aae4
        vector<string>::iterator i, j;
Packit a4aae4
        for (i = cached_headers.begin(), j = headers->begin(); i != cached_headers.end() && j != headers->end();
Packit a4aae4
            ++i, ++j) {
Packit a4aae4
            string ch = (*i).substr(0, (*i).find(": "));
Packit a4aae4
            // Skip over headers that won't be cached. jhrg 7/4/05
Packit a4aae4
            while (is_hop_by_hop_header(*j))
Packit a4aae4
                ++j;
Packit a4aae4
            string h = (*j).substr(0, (*j).find(": "));
Packit a4aae4
            DBG(cerr << "cached: " << ch << ", header: " << h << endl);
Packit a4aae4
            CPPUNIT_ASSERT(ch == h);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
#ifdef DODS_DEBUG
Packit a4aae4
        std::ostream_iterator<string> out_it(std::cerr, "\n");
Packit a4aae4
        cerr << "Cached headers: ";
Packit a4aae4
        std::copy(cached_headers.begin(), cached_headers.end(), out_it);
Packit a4aae4
        cerr << "Headers: ";
Packit a4aae4
        std::copy(headers->begin(), headers->end(), out_it);
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
        CPPUNIT_ASSERT(i == cached_headers.end());
Packit a4aae4
        // This may not be true if. For example, keep-alive might appear in the list of headers
Packit a4aae4
        // received, but not in the list of headers cached.
Packit a4aae4
        // CPPUNIT_ASSERT(j == headers->end());
Packit a4aae4
Packit a4aae4
        // every byte of the cached_body and response body should match.
Packit a4aae4
        while (!feof(rs->get_stream()) && !feof(cached_body) && !ferror(rs->get_stream()) && !ferror(cached_body)) {
Packit a4aae4
            char cb, b;
Packit a4aae4
            int cn = fread(&cb, 1, 1, cached_body);
Packit a4aae4
            int n = fread(&b, 1, 1, rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(cn == n);
Packit a4aae4
            if (cn == 1) CPPUNIT_ASSERT(cb == b);
Packit a4aae4
        }
Packit a4aae4
        CPPUNIT_ASSERT(feof(rs->get_stream()) && feof(cached_body));
Packit a4aae4
Packit a4aae4
        hc->release_cached_response(cached_body);
Packit a4aae4
        delete rs;
Packit a4aae4
        rs = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void perform_garbage_collection_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            delete hc;
Packit a4aae4
            hc = 0;
Packit a4aae4
            auto_ptr<HTTPCache> gc(new HTTPCache("cache-testsuite/gc_cache", true));
Packit a4aae4
            DBG(cerr << "get_cache_root: " << gc->get_cache_root() << endl);
Packit a4aae4
Packit a4aae4
            HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
            gc->cache_response(localhost_url, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(gc->is_url_in_cache(localhost_url));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
Packit a4aae4
            rs = http_conn->fetch_url(expired);
Packit a4aae4
            gc->cache_response(expired, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(gc->is_url_in_cache(expired));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
Packit a4aae4
            sleep(2);
Packit a4aae4
Packit a4aae4
            gc->perform_garbage_collection();
Packit a4aae4
            gc->d_http_cache_table->cache_index_write();
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(
Packit a4aae4
                !gc->is_url_in_cache(expired) && "This may fail if sleep is not long enough before gc above");
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            cerr << "Exception: " << e.get_error_message() << endl;
Packit a4aae4
            CPPUNIT_ASSERT(false);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void purge_cache_and_release_cached_response_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> pc(new HTTPCache("cache-testsuite/purge_cache", true));
Packit a4aae4
            DBG(cerr << "get_cache_root: " << pc->get_cache_root() << endl);
Packit a4aae4
Packit a4aae4
            time_t now = time(0);
Packit a4aae4
            HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
            pc->cache_response(localhost_url, now, *(rs->get_headers()), rs->get_stream());
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(pc->is_url_in_cache(localhost_url));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
Packit a4aae4
            string expired = "http://test.opendap.org/cgi-bin/expires.sh";
Packit a4aae4
            now = time(0);
Packit a4aae4
            rs = http_conn->fetch_url(expired);
Packit a4aae4
            pc->cache_response(expired, now, *(rs->get_headers()), rs->get_stream());
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(pc->is_url_in_cache(expired));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
Packit a4aae4
            HTTPCacheTable::CacheEntry *e1 = pc->d_http_cache_table->get_locked_entry_from_cache_table(expired);
Packit a4aae4
            HTTPCacheTable::CacheEntry *e2 = pc->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
            string e1_file = e1->cachename;
Packit a4aae4
            string e2_file = e2->cachename;
Packit a4aae4
            e1->unlock_read_response();
Packit a4aae4
            e2->unlock_read_response();
Packit a4aae4
Packit a4aae4
            vector<string> headers;
Packit a4aae4
            FILE *b = pc->get_cached_response(expired, headers);
Packit a4aae4
Packit a4aae4
            try {
Packit a4aae4
                pc->purge_cache();
Packit a4aae4
                CPPUNIT_ASSERT(!"This call should throw Error");
Packit a4aae4
            }
Packit a4aae4
            catch (Error &e) {
Packit a4aae4
                CPPUNIT_ASSERT("Caught Error as expected");
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            pc->release_cached_response(b);
Packit a4aae4
Packit a4aae4
            pc->purge_cache();
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(!pc->is_url_in_cache(localhost_url));
Packit a4aae4
            CPPUNIT_ASSERT(!pc->is_url_in_cache(expired));
Packit a4aae4
            CPPUNIT_ASSERT(access(e1_file.c_str(), F_OK) != 0);
Packit a4aae4
            CPPUNIT_ASSERT(access(e2_file.c_str(), F_OK) != 0);
Packit a4aae4
            CPPUNIT_ASSERT(pc->d_http_cache_table->d_current_size == 0);
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            cerr << "Exception: " << e.get_error_message() << endl;
Packit a4aae4
            CPPUNIT_ASSERT(false);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void instance_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            // FIXME: Explain
Packit a4aae4
            HTTPCache::delete_instance();
Packit a4aae4
Packit a4aae4
            HTTPCache *c = HTTPCache::instance("cache-testsuite/singleton_cache", true);
Packit a4aae4
            DBG(cerr << "get_cache_root: " << c->get_cache_root() << endl);
Packit a4aae4
Packit a4aae4
            if (!c->is_url_in_cache(localhost_url)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
                c->cache_response(localhost_url, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
                rs = 0;
Packit a4aae4
            }
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(localhost_url));
Packit a4aae4
Packit a4aae4
            if (!c->is_url_in_cache(expired)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(expired);
Packit a4aae4
                c->cache_response(expired, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
                rs = 0;
Packit a4aae4
            }
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(expired));
Packit a4aae4
Packit a4aae4
            HTTPCacheTable::CacheEntry *e1 = c->d_http_cache_table->get_locked_entry_from_cache_table(expired);
Packit a4aae4
            HTTPCacheTable::CacheEntry *e2 = c->d_http_cache_table->get_locked_entry_from_cache_table(localhost_url);
Packit a4aae4
            string e1_file = e1->cachename;
Packit a4aae4
            string e2_file = e2->cachename;
Packit a4aae4
            e1->unlock_read_response();
Packit a4aae4
            e2->unlock_read_response();
Packit a4aae4
Packit a4aae4
            c->purge_cache();
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(!c->is_url_in_cache(localhost_url));
Packit a4aae4
            CPPUNIT_ASSERT(!c->is_url_in_cache(expired));
Packit a4aae4
            CPPUNIT_ASSERT(access(e1_file.c_str(), F_OK) != 0);
Packit a4aae4
            CPPUNIT_ASSERT(access(e2_file.c_str(), F_OK) != 0);
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            cerr << "Exception: " << e.get_error_message() << endl;
Packit a4aae4
            CPPUNIT_ASSERT(false);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        // Call this here to simulate exiting the program. This ensures that
Packit a4aae4
        // the next test's call to instance() gets a fresh cache. The static
Packit a4aae4
        // method will still be run at exit, but that's OK since it tests the
Packit a4aae4
        // value of _instance and simply returns with it's zero.
Packit a4aae4
        HTTPCache::delete_instance();
Packit a4aae4
#ifndef WIN32
Packit a4aae4
        SignalHandler::delete_instance();
Packit a4aae4
#endif
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void get_conditional_response_headers_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> c(new HTTPCache("cache-testsuite/header_cache", true));
Packit a4aae4
            DBG(cerr << "get_cache_root: " << c->get_cache_root() << endl);
Packit a4aae4
Packit a4aae4
            CPPUNIT_ASSERT(c->get_cache_root() == "cache-testsuite/header_cache/");
Packit a4aae4
            if (!c->is_url_in_cache(localhost_url)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
                c->cache_response(localhost_url, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
            }
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(localhost_url));
Packit a4aae4
Packit a4aae4
            if (!c->is_url_in_cache(expired)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(expired);
Packit a4aae4
                c->cache_response(expired, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
            }
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(expired));
Packit a4aae4
Packit a4aae4
            vector<string> h = c->get_conditional_request_headers(localhost_url);
Packit a4aae4
            DBG(copy(h.begin(), h.end(), ostream_iterator<string>(cout, "\n")));
Packit a4aae4
            DBG(cerr << "if none match location: " << h[0].find("If-None-Match: ") << endl);
Packit a4aae4
            // I know what the strings should start with...
Packit a4aae4
            CPPUNIT_ASSERT(h[0].find("If-None-Match: ") == 0);
Packit a4aae4
Packit a4aae4
            h = c->get_conditional_request_headers(expired);
Packit a4aae4
            DBG(cerr << "Number of headers: " << h.size() << endl);
Packit a4aae4
            DBG(copy(h.begin(), h.end(), ostream_iterator<string>(cout, "\n")));
Packit a4aae4
            CPPUNIT_ASSERT(h[0].find("If-Modified-Since: ") == 0);
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void update_response_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> c(new HTTPCache("cache-testsuite/singleton_cache", true));
Packit a4aae4
            DBG(cerr << "get_cache_root: " << c->get_cache_root() << endl);
Packit a4aae4
Packit a4aae4
            if (!c->is_url_in_cache(localhost_url)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(localhost_url);
Packit a4aae4
                c->cache_response(localhost_url, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            if (!c->is_url_in_cache(expired)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(expired);
Packit a4aae4
                c->cache_response(expired, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                delete rs;
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            // Yes, there's stuff here.
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(localhost_url));
Packit a4aae4
            CPPUNIT_ASSERT(c->is_url_in_cache(expired));
Packit a4aae4
Packit a4aae4
            vector<string> orig_h;
Packit a4aae4
            FILE *cr = c->get_cached_response(localhost_url, orig_h);
Packit a4aae4
Packit a4aae4
            DBG(copy(orig_h.begin(), orig_h.end(), ostream_iterator<string>(cerr, "\n")));
Packit a4aae4
Packit a4aae4
            // Before we merge, et c., check that the headers we're going to
Packit a4aae4
            // poke in aren't already there.
Packit a4aae4
            CPPUNIT_ASSERT(find(orig_h.begin(), orig_h.end(), "XHTTPCache: 123456789") == orig_h.end());
Packit a4aae4
            CPPUNIT_ASSERT(find(orig_h.begin(), orig_h.end(), "Date: <invalid date>") == orig_h.end());
Packit a4aae4
Packit a4aae4
            // Make up some new headers.
Packit a4aae4
            vector<string> new_h;
Packit a4aae4
            new_h.push_back("XHTTPCache: 123456789");
Packit a4aae4
            new_h.push_back("Date: <invalid date>");
Packit a4aae4
Packit a4aae4
            c->release_cached_response(cr);
Packit a4aae4
Packit a4aae4
            c->update_response(localhost_url, time(0), new_h);
Packit a4aae4
Packit a4aae4
            vector<string> updated_h;
Packit a4aae4
            cr = c->get_cached_response(localhost_url, updated_h);
Packit a4aae4
            c->release_cached_response(cr);
Packit a4aae4
Packit a4aae4
            DBG(cerr << endl);
Packit a4aae4
            DBG(copy(updated_h.begin(), updated_h.end(), ostream_iterator<string>(cerr, "\n")));
Packit a4aae4
Packit a4aae4
            // The XHTTPCacheTest header should be new, Date should replace the
Packit a4aae4
            // existing Date header.
Packit a4aae4
            // This may not be true when using distcheck and/or when the user
Packit a4aae4
            // has set USE_CACHE to 1 in their .dodsrc. jhrg 9/29/15
Packit a4aae4
            // CPPUNIT_ASSERT(orig_h.size() + 1 == updated_h.size());
Packit a4aae4
            CPPUNIT_ASSERT(find(updated_h.begin(), updated_h.end(), "XHTTPCache: 123456789") != updated_h.end());
Packit a4aae4
            CPPUNIT_ASSERT(find(updated_h.begin(), updated_h.end(), "Date: <invalid date>") != updated_h.end());
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // Only run this interactively since you need to hit Ctrl-c to generate
Packit a4aae4
    // SIGINT while the cache is doing its thing. 02/10/04 jhrg
Packit a4aae4
    void interrupt_test()
Packit a4aae4
    {
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> c(new HTTPCache("cache-testsuite/singleton_cache", true));
Packit a4aae4
            string coads = "http://test.opendap.org/dap/data/nc/coads_climatology.nc";
Packit a4aae4
            if (!c->is_url_in_cache(coads)) {
Packit a4aae4
                HTTPResponse *rs = http_conn->fetch_url(coads);
Packit a4aae4
                cerr << "In interrupt test, hit ctrl-c now... ";
Packit a4aae4
                c->cache_response(coads, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
                cerr << "to late.";
Packit a4aae4
                delete rs;
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    void cache_gc_test()
Packit a4aae4
    {
Packit a4aae4
        string fnoc1 = "http://test.opendap.org/dap/data/nc/fnoc1.nc.dds";
Packit a4aae4
        string jan = "http://test.opendap.org/dap/data/nc/jan.nc.dds";
Packit a4aae4
        string feb = "http://test.opendap.org/dap/data/nc/feb.nc.dds";
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> pc(new HTTPCache("cache-testsuite/purge_cache", true));
Packit a4aae4
#if 0
Packit a4aae4
            // This broke Fedora ppc64le system with XFS system
Packit a4aae4
            CPPUNIT_ASSERT(pc->d_http_cache_table->d_block_size == 4096);
Packit a4aae4
#endif
Packit a4aae4
            // Change the size parameters so that we can run some tests
Packit a4aae4
            pc->d_total_size = 12288; // bytes
Packit a4aae4
            pc->d_folder_size = pc->d_total_size / 10;
Packit a4aae4
            pc->d_gc_buffer = pc->d_total_size / 10;
Packit a4aae4
Packit a4aae4
            // The cache should start empty
Packit a4aae4
            CPPUNIT_ASSERT(pc->d_http_cache_table->d_current_size == 0);
Packit a4aae4
Packit a4aae4
            // Get a url
Packit a4aae4
            HTTPResponse *rs = http_conn->fetch_url(fnoc1);
Packit a4aae4
            pc->cache_response(fnoc1, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(pc->is_url_in_cache(fnoc1));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
            // trigger a hit for fnoc1
Packit a4aae4
            vector<string> h;
Packit a4aae4
            FILE *f = pc->get_cached_response(fnoc1, h);
Packit a4aae4
            pc->release_cached_response(f);
Packit a4aae4
Packit a4aae4
            rs = http_conn->fetch_url(jan);
Packit a4aae4
            pc->cache_response(jan, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(pc->is_url_in_cache(jan));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
            // trigger two hits for jan
Packit a4aae4
            f = pc->get_cached_response(jan, h);
Packit a4aae4
            pc->release_cached_response(f);
Packit a4aae4
            f = pc->get_cached_response(jan, h);
Packit a4aae4
            pc->release_cached_response(f);
Packit a4aae4
Packit a4aae4
            rs = http_conn->fetch_url(feb);
Packit a4aae4
            pc->cache_response(feb, time(0), *(rs->get_headers()), rs->get_stream());
Packit a4aae4
            CPPUNIT_ASSERT(pc->is_url_in_cache(feb));
Packit a4aae4
            delete rs;
Packit a4aae4
            rs = 0;
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        // now that pc is out of scope, its dtor has been run and GC
Packit a4aae4
        // performed. The feb URL should have been deleted.
Packit a4aae4
Packit a4aae4
        try {
Packit a4aae4
            auto_ptr<HTTPCache> pc(new HTTPCache("cache-testsuite/purge_cache", true));
Packit a4aae4
            CPPUNIT_ASSERT(!pc->is_url_in_cache(feb));
Packit a4aae4
        }
Packit a4aae4
        catch (Error &e) {
Packit a4aae4
            CPPUNIT_FAIL(e.get_error_message());
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
CPPUNIT_TEST_SUITE_REGISTRATION (HTTPCacheTest);
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4
Packit a4aae4
int main(int argc, char*argv[])
Packit a4aae4
{
Packit a4aae4
    GetOpt getopt(argc, argv, "dh");
Packit a4aae4
    int option_char;
Packit a4aae4
Packit a4aae4
    while ((option_char = getopt()) != -1)
Packit a4aae4
        switch (option_char) {
Packit a4aae4
        case 'd':
Packit a4aae4
            debug = 1;  // debug is a static global
Packit a4aae4
            break;
Packit a4aae4
        case 'h': {     // help - show test names
Packit a4aae4
            cerr << "Usage: HTTPCacheTest has the following tests:" << endl;
Packit a4aae4
            const std::vector<Test*> &tests = libdap::HTTPCacheTest::suite()->getTests();
Packit a4aae4
            unsigned int prefix_len = libdap::HTTPCacheTest::suite()->getName().append("::").length();
Packit a4aae4
            for (std::vector<Test*>::const_iterator i = tests.begin(), e = tests.end(); i != e; ++i) {
Packit a4aae4
                cerr << (*i)->getName().replace(0, prefix_len, "") << endl;
Packit a4aae4
            }
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
        default:
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
    // Run cleanup here, so that the first run works (since this code now
Packit a4aae4
    // sets up the tests).
Packit a4aae4
    // This gives valgrind fits...
Packit a4aae4
    system("cd cache-testsuite && ./cleanup.sh");
Packit a4aae4
Packit a4aae4
    CppUnit::TextTestRunner runner;
Packit a4aae4
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
Packit a4aae4
Packit a4aae4
    bool wasSuccessful = true;
Packit a4aae4
    string test = "";
Packit a4aae4
    int i = getopt.optind;
Packit a4aae4
    if (i == argc) {
Packit a4aae4
        // run them all
Packit a4aae4
        wasSuccessful = runner.run("");
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        for (; i < argc; ++i) {
Packit a4aae4
            if (debug) cerr << "Running " << argv[i] << endl;
Packit a4aae4
            test = libdap::HTTPCacheTest::suite()->getName().append("::").append(argv[i]);
Packit a4aae4
            wasSuccessful = wasSuccessful && runner.run(test);
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return wasSuccessful ? 0 : 1;
Packit a4aae4
}
Packit a4aae4