/*
 * Copyright 2012 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: mukerjee@google.com (Matt Mukerjee)

// Unit-test for ExperimentMatcher

#include "net/instaweb/rewriter/public/experiment_matcher.h"

#include "net/instaweb/rewriter/public/experiment_util.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_options_test_base.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/null_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/time_util.h"
#include "pagespeed/kernel/http/http_names.h"  // for HttpAttributes, etc
#include "pagespeed/kernel/http/user_agent_matcher.h"
#include "pagespeed/kernel/http/user_agent_matcher_test_base.h"  // for User Agent constants
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"

namespace net_instaweb {

class ExperimentMatcherTest : public RewriteOptionsTestBase<RewriteOptions> {
 protected:
  ExperimentMatcher experiment_matcher_;
};

// Test that the experiment utils are working together correctly. First tests
// that we can add an experiment spec then classifies the client into an
// experiment. Then manually inserts a cookie and checks that client will not
// ask for another cookie. Then we remove this cookie and ask for classification
// again. We then have the experiment frameworka store what side of the
// experiment we ended on in a cookie for us, which we also check.
TEST_F(ExperimentMatcherTest, ClassifyIntoExperiment) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));
  ASSERT_EQ(1, options.num_experiments());
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(req_headers,
                                                                matcher,
                                                                &options);

  // We expect 1 here because we set up an experiment above (id=1;percent=100)
  // that takes 100% of the traffic and puts it into an experiment with id=1.
  ASSERT_EQ(1, options.experiment_id());
  ASSERT_TRUE(need_cookie);

  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=1");
  need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_FALSE(need_cookie);

  experiment::RemoveExperimentCookie(&req_headers);
  need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);

  // Same as above comment.
  ASSERT_EQ(1, options.experiment_id());
  ASSERT_TRUE(need_cookie);

  // Same test used for experiment::SetExperimentCookie in experiment_util_test.
  ResponseHeaders resp_headers;
  GoogleString url = "http://www.test.com/stuff/some_page.html";
  experiment_matcher_.StoreExperimentData(
      options.experiment_id(), url, 0, &resp_headers);
  ASSERT_TRUE(resp_headers.Has(HttpAttributes::kSetCookie));
  ConstStringStarVector v;
  EXPECT_TRUE(resp_headers.Lookup(HttpAttributes::kSetCookie, &v));
  ASSERT_EQ(1, v.size());
  GoogleString expires;
  ConvertTimeToString(0, &expires);
  GoogleString expected = StringPrintf(
      "PageSpeedExperiment=1; Expires=%s; Domain=.www.test.com; Path=/",
      expires.c_str());
  EXPECT_EQ(expected, *v[0]);
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentStaleCookie) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));

  // Test that a new cookie is set when the incoming cookie has an invalid id.
  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=4");
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_TRUE(need_cookie);
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentNoExptCookie) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));

  // Test that a new cookie is not assigned when the incoming cookie has the
  // no-expt cookie.
  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=0");
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_FALSE(need_cookie);
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentEnrollExperiment) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  options.set_enroll_experiment_id(0);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));

  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=1");

  // User should be force-assigned to id=0, even though 0 is for 0% of users and
  // they're already in group 1.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_TRUE(need_cookie);
  ASSERT_EQ(0, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentEnrollNotSet) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  options.set_enroll_experiment_id(experiment::kExperimentNotSet);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));

  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=0");

  // User should be assigned to id=1, even though they're already in group 0.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_TRUE(need_cookie);
  ASSERT_EQ(1, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentEnrollBadNum) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  options.set_enroll_experiment_id(2);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=100", &handler));

  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=0");

  // User should remain in group 0 because forcing a nonexistent experiment
  // should do nothing.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_FALSE(need_cookie);
  ASSERT_EQ(0, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentNoActiveExperiments) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=0", &handler));

  // No cookie should be set because there's no active experiment.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_FALSE(need_cookie);
  ASSERT_EQ(experiment::kExperimentNotSet, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentNoActiveExperimentsKeep) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=0", &handler));

  req_headers.Add(HttpAttributes::kCookie, "PageSpeedExperiment=1");

  // Even though there's no active experiment, keep the user in group 1.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_FALSE(need_cookie);
  ASSERT_EQ(1, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentNoActiveExperimentsUnset) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  options.set_enroll_experiment_id(experiment::kExperimentNotSet);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=0", &handler));

  // Normally no cookie would be set because there's no active experiment, but
  // we forced kExperimentNotSet which is for resetting cookie values so set the
  // cookie to 0.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_TRUE(need_cookie);
  ASSERT_EQ(0, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ClassifyIntoExperimentNoActiveExperimentsEnroll) {
  RequestHeaders req_headers;
  RewriteOptions options(thread_system_.get());
  options.set_running_experiment(true);
  options.set_enroll_experiment_id(1);
  NullMessageHandler handler;
  UserAgentMatcher matcher;
  ASSERT_TRUE(options.AddExperimentSpec("id=1;percent=0", &handler));

  // We should still be able to force-assign users to percent=0 categories.
  bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(
      req_headers, matcher, &options);
  ASSERT_TRUE(need_cookie);
  ASSERT_EQ(1, options.experiment_id());
}

TEST_F(ExperimentMatcherTest, ExperimentMatchesDeviceType) {
  // Ideally these tests would be performed with a mock UserAgentMatcher,
  // but we don't have one. These constants ought to be good enough.
  {
    // Desktop only experiment does not apply to mobile User Agent
    RequestHeaders req_headers;
    RewriteOptions options(thread_system_.get());
    options.set_running_experiment(true);
    NullMessageHandler handler;
    UserAgentMatcher matcher;

    ASSERT_TRUE(options.AddExperimentSpec(
        "id=1;percent=100;matches_device_type=desktop", &handler));

    req_headers.Replace(HttpAttributes::kUserAgent,
                        UserAgentMatcherTestBase::kAndroidChrome21UserAgent);

    bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(req_headers,
                                                                  matcher,
                                                                  &options);

    ASSERT_TRUE(need_cookie);
    EXPECT_EQ(0, options.experiment_id());
  }
  {
    // Desktop only experiment applies to desktop User Agent
    RequestHeaders req_headers;
    RewriteOptions options(thread_system_.get());
    options.set_running_experiment(true);
    NullMessageHandler handler;
    UserAgentMatcher matcher;

    ASSERT_TRUE(options.AddExperimentSpec(
        "id=1;percent=100;matches_device_type=desktop", &handler));

    req_headers.Replace(HttpAttributes::kUserAgent,
                        UserAgentMatcherTestBase::kChrome18UserAgent);

    bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(req_headers,
                                                                  matcher,
                                                                  &options);

    ASSERT_TRUE(need_cookie);
    EXPECT_EQ(1, options.experiment_id());
  }
  {
    // tablet+mobile experiment applies to tablet User Agent
    RequestHeaders req_headers;
    RewriteOptions options(thread_system_.get());
    options.set_running_experiment(true);
    NullMessageHandler handler;
    UserAgentMatcher matcher;

    ASSERT_TRUE(options.AddExperimentSpec(
        "id=1;percent=100;matches_device_type=tablet,mobile", &handler));

    req_headers.Replace(HttpAttributes::kUserAgent,
                        UserAgentMatcherTestBase::kIPadChrome36UserAgent);

    bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(req_headers,
                                                                  matcher,
                                                                  &options);

    ASSERT_TRUE(need_cookie);
    EXPECT_EQ(1, options.experiment_id());
  }
  {
    // tablet+mobile experiment does not apply to desktop User Agent
    RequestHeaders req_headers;
    RewriteOptions options(thread_system_.get());
    options.set_running_experiment(true);
    NullMessageHandler handler;
    UserAgentMatcher matcher;

    ASSERT_TRUE(options.AddExperimentSpec(
        "id=1;percent=100;matches_device_type=tablet,mobile", &handler));

    req_headers.Replace(HttpAttributes::kUserAgent,
                        UserAgentMatcherTestBase::kChrome18UserAgent);

    bool need_cookie = experiment_matcher_.ClassifyIntoExperiment(req_headers,
                                                                  matcher,
                                                                  &options);

    ASSERT_TRUE(need_cookie);
    EXPECT_EQ(0, options.experiment_id());
  }
}


}  // namespace net_instaweb
