#include <iostream>
#include <gtest/gtest.h>
#include <tango_cache_pending.h>

using namespace std;

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

TEST(CacheActionTest, PragmaField)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    struct response_freshness freshness;

    http_heads.http_field = TFE_HTTP_PRAGMA;
    http_heads.value = "no-cache";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1,&restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), REVALIDATE);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
    
}

TEST(CacheActionTest, CacheCtlNoCache)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "no-cache";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), REVALIDATE);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}

TEST(CacheActionTest, CacheCtlNoStore)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "no-store";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), FORBIDDEN);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), FORBIDDEN);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
TEST(CacheActionTest, CacheCtlCached)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "only-if-cached, max-age=3600";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), ALLOWED);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 3600);
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), ALLOWED);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 3600);
}

TEST(CacheActionTest, CacheCtlMinFresh)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "only-if-cached, max-age=3600, min-fresh=60";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), ALLOWED);
    EXPECT_EQ(restrict.min_fresh, 60);
    EXPECT_EQ(restrict.max_age, 3600);
}

TEST(CacheActionTest, CacheCtlMustRevalidate)
{
    struct tfe_http_field http_heads;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "must-revalidate";
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), REVALIDATE);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
TEST(CacheActionTest, CacheCtlProxyRevalidate)
{
    struct tfe_http_field http_heads;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "proxy-revalidate";
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), REVALIDATE);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
TEST(CacheActionTest, CacheCtlCachedSMaxAge)
{
    struct tfe_http_field http_heads;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "public, max-age=60, s-maxage=3600";
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), ALLOWED);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 3600);
}


TEST(CacheActionTest, CacheCtlPrivate)
{
    struct tfe_http_field http_heads;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_CACHE_CONTROL;
    http_heads.value = "private";
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), FORBIDDEN);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
TEST(CacheActionTest, ExpiresResponse)
{
    struct tfe_http_field http_heads;
    struct response_freshness freshness;
    http_heads.http_field = TFE_HTTP_EXPIRES;
    http_heads.value = "Sun, 01 Dec 2019 16:00:00 GMT";
    EXPECT_EQ(tfe_cache_put_pending(&http_heads, 1, &freshness), ALLOWED);
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.last_modified, 0);
    cout << freshness.timeout << endl;
}
TEST(CacheActionTest, IfMatchRequest)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    http_heads.http_field = TLF_HTTP_IF_MATCH;
    http_heads.value = "50b1c1d4f775c61:df3";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
}
TEST(CacheActionTest, IfNoMatchRequest)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    http_heads.http_field = TLF_HTTP_IF_NONE_MATCH;
    http_heads.value = "50b1c1d4f775c61:df3";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
}
TEST(CacheActionTest, IfModifiedSinceRequest)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    http_heads.http_field = TLF_HTTP_IF_MODIFIED_SINCE;
    http_heads.value = "Sun, 01 Dec 2019 16:00:00 GMT";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
}
TEST(CacheActionTest, IfUnModifiedSinceRequest)
{
    struct tfe_http_field http_heads;
    struct request_freshness restrict;
    http_heads.http_field = TLF_HTTP_IF_UNMODIFIED_SINCE;
    http_heads.value = "Sun, 01 Dec 2019 16:00:00 GMT";
    EXPECT_EQ(tfe_cache_get_pending(&http_heads, 1, &restrict), REVALIDATE);
    EXPECT_EQ(restrict.min_fresh, 0);
    EXPECT_EQ(restrict.max_age, 0);
}
TEST(CacheActionTest, Date)
{
    struct tfe_http_field http_heads[2];
    struct response_freshness freshness;
    http_heads[0].http_field=TFE_HTTP_CACHE_CONTROL;
    http_heads[0].value = "public, max=3600";
    http_heads[1].http_field = TFE_HTTP_DATE;
    http_heads[1].value = "Sun, 01 Dec 2019 16:00:00 GMT";
    EXPECT_EQ(tfe_cache_put_pending(http_heads, 2, &freshness), ALLOWED);
    cout << freshness.date << endl;
    EXPECT_EQ(freshness.last_modified, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
TEST(CacheActionTest, LastModified)
{
    struct tfe_http_field http_heads[2];
    struct response_freshness freshness;
    http_heads[0].http_field=TFE_HTTP_CACHE_CONTROL;
    http_heads[0].value = "public, max=3600";
    http_heads[1].http_field = TLF_HTTP_LAST_MODIFIED;
    http_heads[1].value = "Sun, 01 Dec 2019 16:00:00 GMT";
    EXPECT_EQ(tfe_cache_put_pending(http_heads, 2, &freshness),ALLOWED);
    cout << freshness.last_modified << endl;
    EXPECT_EQ(freshness.date, 0);
    EXPECT_EQ(freshness.timeout, 0);
}
