// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_sorting.h"

#include <map>

#include "chrome/browser/extensions/extension_prefs_unittest.h"
#include "extensions/common/manifest_constants.h"
#include "sync/api/string_ordinal.h"
#include "testing/gtest/include/gtest/gtest.h"

using extensions::Blacklist;
using extensions::Extension;
using extensions::Manifest;

namespace keys = extensions::manifest_keys;

class ExtensionSortingTest : public extensions::ExtensionPrefsTest {
 protected:
  ExtensionSorting* extension_sorting() {
    return prefs()->extension_sorting();
  }
};

class ExtensionSortingAppLocation : public ExtensionSortingTest {
 public:
  virtual void Initialize() OVERRIDE {
    extension_ = prefs_.AddExtension("not_an_app");
    // Non-apps should not have any app launch ordinal or page ordinal.
    prefs()->OnExtensionInstalled(extension_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());
  }

  virtual void Verify() OVERRIDE {
    EXPECT_FALSE(
        extension_sorting()->GetAppLaunchOrdinal(extension_->id()).IsValid());
    EXPECT_FALSE(
        extension_sorting()->GetPageOrdinal(extension_->id()).IsValid());
  }

 private:
  scoped_refptr<Extension> extension_;
};
TEST_F(ExtensionSortingAppLocation, ExtensionSortingAppLocation) {}

class ExtensionSortingAppLaunchOrdinal : public ExtensionSortingTest {
 public:
  virtual void Initialize() OVERRIDE {
    // No extensions yet.
    syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
    EXPECT_TRUE(syncer::StringOrdinal::CreateInitialOrdinal().Equals(
        extension_sorting()->CreateNextAppLaunchOrdinal(page)));

    extension_ = prefs_.AddApp("on_extension_installed");
    EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id()));
    prefs()->OnExtensionInstalled(extension_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());
  }

  virtual void Verify() OVERRIDE {
    syncer::StringOrdinal launch_ordinal =
        extension_sorting()->GetAppLaunchOrdinal(extension_->id());
    syncer::StringOrdinal page_ordinal =
        syncer::StringOrdinal::CreateInitialOrdinal();

    // Extension should have been assigned a valid StringOrdinal.
    EXPECT_TRUE(launch_ordinal.IsValid());
    EXPECT_TRUE(launch_ordinal.LessThan(
        extension_sorting()->CreateNextAppLaunchOrdinal(page_ordinal)));
    // Set a new launch ordinal of and verify it comes after.
    extension_sorting()->SetAppLaunchOrdinal(
        extension_->id(),
        extension_sorting()->CreateNextAppLaunchOrdinal(page_ordinal));
    syncer::StringOrdinal new_launch_ordinal =
        extension_sorting()->GetAppLaunchOrdinal(extension_->id());
    EXPECT_TRUE(launch_ordinal.LessThan(new_launch_ordinal));

    // This extension doesn't exist, so it should return an invalid
    // StringOrdinal.
    syncer::StringOrdinal invalid_app_launch_ordinal =
        extension_sorting()->GetAppLaunchOrdinal("foo");
    EXPECT_FALSE(invalid_app_launch_ordinal.IsValid());
    EXPECT_EQ(-1, extension_sorting()->PageStringOrdinalAsInteger(
        invalid_app_launch_ordinal));

    // The second page doesn't have any apps so its next launch ordinal should
    // be the first launch ordinal.
    syncer::StringOrdinal next_page = page_ordinal.CreateAfter();
    syncer::StringOrdinal next_page_app_launch_ordinal =
        extension_sorting()->CreateNextAppLaunchOrdinal(next_page);
    EXPECT_TRUE(next_page_app_launch_ordinal.Equals(
        extension_sorting()->CreateFirstAppLaunchOrdinal(next_page)));
  }

 private:
  scoped_refptr<Extension> extension_;
};
TEST_F(ExtensionSortingAppLaunchOrdinal, ExtensionSortingAppLaunchOrdinal) {}

class ExtensionSortingPageOrdinal : public ExtensionSortingTest {
 public:
  virtual void Initialize() OVERRIDE {
    extension_ = prefs_.AddApp("page_ordinal");
    // Install with a page preference.
    first_page_ = syncer::StringOrdinal::CreateInitialOrdinal();
    prefs()->OnExtensionInstalled(extension_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  first_page_);
    EXPECT_TRUE(first_page_.Equals(
        extension_sorting()->GetPageOrdinal(extension_->id())));
    EXPECT_EQ(0, extension_sorting()->PageStringOrdinalAsInteger(first_page_));

    scoped_refptr<Extension> extension2 = prefs_.AddApp("page_ordinal_2");
    // Install without any page preference.
    prefs()->OnExtensionInstalled(extension2.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());
    EXPECT_TRUE(first_page_.Equals(
        extension_sorting()->GetPageOrdinal(extension2->id())));
  }
  virtual void Verify() OVERRIDE {
    // Set the page ordinal.
    syncer::StringOrdinal new_page = first_page_.CreateAfter();
    extension_sorting()->SetPageOrdinal(extension_->id(), new_page);
    // Verify the page ordinal.
    EXPECT_TRUE(
        new_page.Equals(extension_sorting()->GetPageOrdinal(extension_->id())));
    EXPECT_EQ(1, extension_sorting()->PageStringOrdinalAsInteger(new_page));

    // This extension doesn't exist, so it should return an invalid
    // StringOrdinal.
    EXPECT_FALSE(extension_sorting()->GetPageOrdinal("foo").IsValid());
  }

 private:
  syncer::StringOrdinal first_page_;
  scoped_refptr<Extension> extension_;
};
TEST_F(ExtensionSortingPageOrdinal, ExtensionSortingPageOrdinal) {}

// Ensure that ExtensionSorting is able to properly initialize off a set
// of old page and app launch indices and properly convert them.
class ExtensionSortingInitialize
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingInitialize() {}
  virtual ~ExtensionSortingInitialize() {}

  virtual void Initialize() OVERRIDE {
    // A preference determining the order of which the apps appear on the NTP.
    const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
    // A preference determining the page on which an app appears in the NTP.
    const char kPrefPageIndexDeprecated[] = "page_index";

    // Setup the deprecated preferences.
    ExtensionScopedPrefs* scoped_prefs =
        static_cast<ExtensionScopedPrefs*>(prefs());
    scoped_prefs->UpdateExtensionPref(extension1()->id(),
                                      kPrefAppLaunchIndexDeprecated,
                                      new base::FundamentalValue(0));
    scoped_prefs->UpdateExtensionPref(extension1()->id(),
                                      kPrefPageIndexDeprecated,
                                      new base::FundamentalValue(0));

    scoped_prefs->UpdateExtensionPref(extension2()->id(),
                                      kPrefAppLaunchIndexDeprecated,
                                      new base::FundamentalValue(1));
    scoped_prefs->UpdateExtensionPref(extension2()->id(),
                                      kPrefPageIndexDeprecated,
                                      new base::FundamentalValue(0));

    scoped_prefs->UpdateExtensionPref(extension3()->id(),
                                      kPrefAppLaunchIndexDeprecated,
                                      new base::FundamentalValue(0));
    scoped_prefs->UpdateExtensionPref(extension3()->id(),
                                      kPrefPageIndexDeprecated,
                                      new base::FundamentalValue(1));

    // We insert the ids in reserve order so that we have to deal with the
    // element on the 2nd page before the 1st page is seen.
    extensions::ExtensionIdList ids;
    ids.push_back(extension3()->id());
    ids.push_back(extension2()->id());
    ids.push_back(extension1()->id());

    prefs()->extension_sorting()->Initialize(ids);
  }
  virtual void Verify() OVERRIDE {
    syncer::StringOrdinal first_ordinal =
        syncer::StringOrdinal::CreateInitialOrdinal();
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    EXPECT_TRUE(first_ordinal.Equals(
        extension_sorting->GetAppLaunchOrdinal(extension1()->id())));
    EXPECT_TRUE(first_ordinal.LessThan(
        extension_sorting->GetAppLaunchOrdinal(extension2()->id())));
    EXPECT_TRUE(first_ordinal.Equals(
        extension_sorting->GetAppLaunchOrdinal(extension3()->id())));

    EXPECT_TRUE(first_ordinal.Equals(
        extension_sorting->GetPageOrdinal(extension1()->id())));
    EXPECT_TRUE(first_ordinal.Equals(
        extension_sorting->GetPageOrdinal(extension2()->id())));
    EXPECT_TRUE(first_ordinal.LessThan(
        extension_sorting->GetPageOrdinal(extension3()->id())));
  }
};
TEST_F(ExtensionSortingInitialize, ExtensionSortingInitialize) {}

// Make sure that initialization still works when no extensions are present
// (i.e. make sure that the web store icon is still loaded into the map).
class ExtensionSortingInitializeWithNoApps
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingInitializeWithNoApps() {}
  virtual ~ExtensionSortingInitializeWithNoApps() {}

  virtual void Initialize() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Make sure that the web store has valid ordinals.
    syncer::StringOrdinal initial_ordinal =
        syncer::StringOrdinal::CreateInitialOrdinal();
    extension_sorting->SetPageOrdinal(extension_misc::kWebStoreAppId,
                                      initial_ordinal);
    extension_sorting->SetAppLaunchOrdinal(extension_misc::kWebStoreAppId,
                                           initial_ordinal);

    extensions::ExtensionIdList ids;
    extension_sorting->Initialize(ids);
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    syncer::StringOrdinal page =
        extension_sorting->GetPageOrdinal(extension_misc::kWebStoreAppId);
    EXPECT_TRUE(page.IsValid());

    ExtensionSorting::PageOrdinalMap::iterator page_it =
        extension_sorting->ntp_ordinal_map_.find(page);
    EXPECT_TRUE(page_it != extension_sorting->ntp_ordinal_map_.end());

    syncer::StringOrdinal app_launch =
        extension_sorting->GetPageOrdinal(extension_misc::kWebStoreAppId);
    EXPECT_TRUE(app_launch.IsValid());

    ExtensionSorting::AppLaunchOrdinalMap::iterator app_launch_it =
        page_it->second.find(app_launch);
    EXPECT_TRUE(app_launch_it != page_it->second.end());
  }
};
TEST_F(ExtensionSortingInitializeWithNoApps,
       ExtensionSortingInitializeWithNoApps) {}

// Tests the application index to ordinal migration code for values that
// shouldn't be converted. This should be removed when the migrate code
// is taken out.
// http://crbug.com/107376
class ExtensionSortingMigrateAppIndexInvalid
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingMigrateAppIndexInvalid() {}
  virtual ~ExtensionSortingMigrateAppIndexInvalid() {}

  virtual void Initialize() OVERRIDE {
    // A preference determining the order of which the apps appear on the NTP.
    const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
    // A preference determining the page on which an app appears in the NTP.
    const char kPrefPageIndexDeprecated[] = "page_index";

    // Setup the deprecated preference.
    ExtensionScopedPrefs* scoped_prefs =
        static_cast<ExtensionScopedPrefs*>(prefs());
    scoped_prefs->UpdateExtensionPref(extension1()->id(),
                                      kPrefAppLaunchIndexDeprecated,
                                      new base::FundamentalValue(0));
    scoped_prefs->UpdateExtensionPref(extension1()->id(),
                                      kPrefPageIndexDeprecated,
                                      new base::FundamentalValue(-1));

    extensions::ExtensionIdList ids;
    ids.push_back(extension1()->id());

    prefs()->extension_sorting()->Initialize(ids);
  }
  virtual void Verify() OVERRIDE {
    // Make sure that the invalid page_index wasn't converted over.
    EXPECT_FALSE(prefs()->extension_sorting()->GetAppLaunchOrdinal(
        extension1()->id()).IsValid());
  }
};
TEST_F(ExtensionSortingMigrateAppIndexInvalid,
       ExtensionSortingMigrateAppIndexInvalid) {}

class ExtensionSortingFixNTPCollisionsAllCollide
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingFixNTPCollisionsAllCollide() {}
  virtual ~ExtensionSortingFixNTPCollisionsAllCollide() {}

  virtual void Initialize() OVERRIDE {
    repeated_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    extension_sorting->SetAppLaunchOrdinal(extension1()->id(),
                                           repeated_ordinal_);
    extension_sorting->SetPageOrdinal(extension1()->id(), repeated_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension2()->id(),
                                           repeated_ordinal_);
    extension_sorting->SetPageOrdinal(extension2()->id(), repeated_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension3()->id(),
                                           repeated_ordinal_);
    extension_sorting->SetPageOrdinal(extension3()->id(), repeated_ordinal_);

    extension_sorting->FixNTPOrdinalCollisions();
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    syncer::StringOrdinal extension1_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension1()->id());
    syncer::StringOrdinal extension2_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension2()->id());
    syncer::StringOrdinal extension3_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension3()->id());

    // The overlapping extensions should have be adjusted so that they are
    // sorted by their id.
    EXPECT_EQ(extension1()->id() < extension2()->id(),
              extension1_app_launch.LessThan(extension2_app_launch));
    EXPECT_EQ(extension1()->id() < extension3()->id(),
              extension1_app_launch.LessThan(extension3_app_launch));
    EXPECT_EQ(extension2()->id() < extension3()->id(),
              extension2_app_launch.LessThan(extension3_app_launch));

    // The page ordinal should be unchanged.
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension1()->id()).Equals(
        repeated_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension2()->id()).Equals(
        repeated_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension3()->id()).Equals(
        repeated_ordinal_));
  }

 private:
  syncer::StringOrdinal repeated_ordinal_;
};
TEST_F(ExtensionSortingFixNTPCollisionsAllCollide,
       ExtensionSortingFixNTPCollisionsAllCollide) {}

class ExtensionSortingFixNTPCollisionsSomeCollideAtStart
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingFixNTPCollisionsSomeCollideAtStart() {}
  virtual ~ExtensionSortingFixNTPCollisionsSomeCollideAtStart() {}

  virtual void Initialize() OVERRIDE {
    first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
    syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Have the first two extension in the same position, with a third
    // (non-colliding) extension after.

    extension_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
    extension_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
    extension_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
    extension_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);

    extension_sorting->FixNTPOrdinalCollisions();
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    syncer::StringOrdinal extension1_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension1()->id());
    syncer::StringOrdinal extension2_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension2()->id());
    syncer::StringOrdinal extension3_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension3()->id());

    // The overlapping extensions should have be adjusted so that they are
    // sorted by their id, but they both should be before ext3, which wasn't
    // overlapping.
    EXPECT_EQ(extension1()->id() < extension2()->id(),
              extension1_app_launch.LessThan(extension2_app_launch));
    EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
    EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));

    // The page ordinal should be unchanged.
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension1()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension2()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension3()->id()).Equals(
        first_ordinal_));
  }

 private:
  syncer::StringOrdinal first_ordinal_;
};
TEST_F(ExtensionSortingFixNTPCollisionsSomeCollideAtStart,
       ExtensionSortingFixNTPCollisionsSomeCollideAtStart) {}

class ExtensionSortingFixNTPCollisionsSomeCollideAtEnd
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingFixNTPCollisionsSomeCollideAtEnd() {}
  virtual ~ExtensionSortingFixNTPCollisionsSomeCollideAtEnd() {}

  virtual void Initialize() OVERRIDE {
    first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
    syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Have the first extension in a non-colliding position, followed by two
    // two extension in the same position.

    extension_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
    extension_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension2()->id(), second_ordinal);
    extension_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
    extension_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);

    extension_sorting->FixNTPOrdinalCollisions();
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    syncer::StringOrdinal extension1_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension1()->id());
    syncer::StringOrdinal extension2_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension2()->id());
    syncer::StringOrdinal extension3_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension3()->id());

    // The overlapping extensions should have be adjusted so that they are
    // sorted by their id, but they both should be after ext1, which wasn't
    // overlapping.
    EXPECT_TRUE(extension1_app_launch.LessThan(extension2_app_launch));
    EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
    EXPECT_EQ(extension2()->id() < extension3()->id(),
              extension2_app_launch.LessThan(extension3_app_launch));

    // The page ordinal should be unchanged.
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension1()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension2()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension3()->id()).Equals(
        first_ordinal_));
  }

 private:
  syncer::StringOrdinal first_ordinal_;
};
TEST_F(ExtensionSortingFixNTPCollisionsSomeCollideAtEnd,
       ExtensionSortingFixNTPCollisionsSomeCollideAtEnd) {}

class ExtensionSortingFixNTPCollisionsTwoCollisions
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingFixNTPCollisionsTwoCollisions() {}
  virtual ~ExtensionSortingFixNTPCollisionsTwoCollisions() {}

  virtual void Initialize() OVERRIDE {
    first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
    syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Have two extensions colliding, followed by two more colliding extensions.
    extension_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
    extension_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
    extension_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
    extension_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);

    extension_sorting->SetAppLaunchOrdinal(extension4()->id(), second_ordinal);
    extension_sorting->SetPageOrdinal(extension4()->id(), first_ordinal_);

    extension_sorting->FixNTPOrdinalCollisions();
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    syncer::StringOrdinal extension1_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension1()->id());
    syncer::StringOrdinal extension2_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension2()->id());
    syncer::StringOrdinal extension3_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension3()->id());
    syncer::StringOrdinal extension4_app_launch =
        extension_sorting->GetAppLaunchOrdinal(extension4()->id());

    // The overlapping extensions should have be adjusted so that they are
    // sorted by their id, with |ext1| and |ext2| appearing before |ext3| and
    // |ext4|.
    EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
    EXPECT_TRUE(extension1_app_launch.LessThan(extension4_app_launch));
    EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
    EXPECT_TRUE(extension2_app_launch.LessThan(extension4_app_launch));

    EXPECT_EQ(extension1()->id() < extension2()->id(),
              extension1_app_launch.LessThan(extension2_app_launch));
    EXPECT_EQ(extension3()->id() < extension4()->id(),
              extension3_app_launch.LessThan(extension4_app_launch));

    // The page ordinal should be unchanged.
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension1()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension2()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension3()->id()).Equals(
        first_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(extension4()->id()).Equals(
        first_ordinal_));
  }

 private:
  syncer::StringOrdinal first_ordinal_;
};
TEST_F(ExtensionSortingFixNTPCollisionsTwoCollisions,
       ExtensionSortingFixNTPCollisionsTwoCollisions) {}

class ExtensionSortingEnsureValidOrdinals
    : public extensions::PrefsPrepopulatedTestBase {
 public :
  ExtensionSortingEnsureValidOrdinals() {}
  virtual ~ExtensionSortingEnsureValidOrdinals() {}

  virtual void Initialize() OVERRIDE {}
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Give ext1 invalid ordinals and then check that EnsureValidOrdinals fixes
    // them.
    extension_sorting->SetAppLaunchOrdinal(extension1()->id(),
                                           syncer::StringOrdinal());
    extension_sorting->SetPageOrdinal(extension1()->id(),
                                      syncer::StringOrdinal());

    extension_sorting->EnsureValidOrdinals(extension1()->id(),
                                           syncer::StringOrdinal());

    EXPECT_TRUE(
        extension_sorting->GetAppLaunchOrdinal(extension1()->id()).IsValid());
    EXPECT_TRUE(
        extension_sorting->GetPageOrdinal(extension1()->id()).IsValid());
  }
};
TEST_F(ExtensionSortingEnsureValidOrdinals,
       ExtensionSortingEnsureValidOrdinals) {}

class ExtensionSortingPageOrdinalMapping
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingPageOrdinalMapping() {}
  virtual ~ExtensionSortingPageOrdinalMapping() {}

  virtual void Initialize() OVERRIDE {}
  virtual void Verify() OVERRIDE {
    std::string ext_1 = "ext_1";
    std::string ext_2 = "ext_2";

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    syncer::StringOrdinal first_ordinal =
        syncer::StringOrdinal::CreateInitialOrdinal();

    // Ensure attempting to removing a mapping with an invalid page doesn't
    // modify the map.
    EXPECT_TRUE(extension_sorting->ntp_ordinal_map_.empty());
    extension_sorting->RemoveOrdinalMapping(
        ext_1, first_ordinal, first_ordinal);
    EXPECT_TRUE(extension_sorting->ntp_ordinal_map_.empty());

    // Add new mappings.
    extension_sorting->AddOrdinalMapping(ext_1, first_ordinal, first_ordinal);
    extension_sorting->AddOrdinalMapping(ext_2, first_ordinal, first_ordinal);

    EXPECT_EQ(1U, extension_sorting->ntp_ordinal_map_.size());
    EXPECT_EQ(2U, extension_sorting->ntp_ordinal_map_[first_ordinal].size());

    ExtensionSorting::AppLaunchOrdinalMap::iterator it =
        extension_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
    EXPECT_EQ(ext_1, it->second);
    ++it;
    EXPECT_EQ(ext_2, it->second);

    extension_sorting->RemoveOrdinalMapping(ext_1,
                                            first_ordinal,
                                            first_ordinal);
    EXPECT_EQ(1U, extension_sorting->ntp_ordinal_map_.size());
    EXPECT_EQ(1U, extension_sorting->ntp_ordinal_map_[first_ordinal].size());

    it = extension_sorting->ntp_ordinal_map_[first_ordinal].find(
        first_ordinal);
    EXPECT_EQ(ext_2, it->second);

    // Ensure that attempting to remove an extension with a valid page and app
    // launch ordinals, but a unused id has no effect.
    extension_sorting->RemoveOrdinalMapping(
        "invalid_ext", first_ordinal, first_ordinal);
    EXPECT_EQ(1U, extension_sorting->ntp_ordinal_map_.size());
    EXPECT_EQ(1U, extension_sorting->ntp_ordinal_map_[first_ordinal].size());

    it = extension_sorting->ntp_ordinal_map_[first_ordinal].find(
        first_ordinal);
    EXPECT_EQ(ext_2, it->second);
  }
};
TEST_F(ExtensionSortingPageOrdinalMapping,
       ExtensionSortingPageOrdinalMapping) {}

class ExtensionSortingPreinstalledAppsBase
    : public extensions::PrefsPrepopulatedTestBase {
 public:
  ExtensionSortingPreinstalledAppsBase() {
    DictionaryValue simple_dict;
    simple_dict.SetString(keys::kVersion, "1.0.0.0");
    simple_dict.SetString(keys::kName, "unused");
    simple_dict.SetString(keys::kApp, "true");
    simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");

    std::string error;
    app1_scoped_ = Extension::Create(
        prefs_.temp_dir().AppendASCII("app1_"), Manifest::EXTERNAL_PREF,
        simple_dict, Extension::NO_FLAGS, &error);
    prefs()->OnExtensionInstalled(app1_scoped_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());

    app2_scoped_ = Extension::Create(
        prefs_.temp_dir().AppendASCII("app2_"), Manifest::EXTERNAL_PREF,
        simple_dict, Extension::NO_FLAGS, &error);
    prefs()->OnExtensionInstalled(app2_scoped_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());

    app1_ = app1_scoped_.get();
    app2_ = app2_scoped_.get();
  }
  virtual ~ExtensionSortingPreinstalledAppsBase() {}

 protected:
  // Weak references, for convenience.
  Extension* app1_;
  Extension* app2_;

 private:
  scoped_refptr<Extension> app1_scoped_;
  scoped_refptr<Extension> app2_scoped_;
};

class ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage
    : public ExtensionSortingPreinstalledAppsBase {
 public:
  ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}
  virtual ~ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}

  virtual void Initialize() OVERRIDE {}
  virtual void Verify() OVERRIDE {
    syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    syncer::StringOrdinal min =
        extension_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
            page,
            ExtensionSorting::MIN_ORDINAL);
    syncer::StringOrdinal max =
        extension_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
            page,
            ExtensionSorting::MAX_ORDINAL);
    EXPECT_TRUE(min.IsValid());
    EXPECT_TRUE(max.IsValid());
    EXPECT_TRUE(min.LessThan(max));

    // Ensure that the min and max values aren't set for empty pages.
    min = syncer::StringOrdinal();
    max = syncer::StringOrdinal();
    syncer::StringOrdinal empty_page = page.CreateAfter();
    EXPECT_FALSE(min.IsValid());
    EXPECT_FALSE(max.IsValid());
    min = extension_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
        empty_page,
        ExtensionSorting::MIN_ORDINAL);
    max = extension_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
        empty_page,
        ExtensionSorting::MAX_ORDINAL);
    EXPECT_FALSE(min.IsValid());
    EXPECT_FALSE(max.IsValid());
  }
};
TEST_F(ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage,
       ExtensionSortingGetMinOrMaxAppLaunchOrdinalsOnPage) {}

// Make sure that empty pages aren't removed from the integer to ordinal
// mapping. See http://crbug.com/109802 for details.
class ExtensionSortingKeepEmptyStringOrdinalPages
    : public ExtensionSortingPreinstalledAppsBase {
 public:
  ExtensionSortingKeepEmptyStringOrdinalPages() {}
  virtual ~ExtensionSortingKeepEmptyStringOrdinalPages() {}

  virtual void Initialize() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    syncer::StringOrdinal first_page =
        syncer::StringOrdinal::CreateInitialOrdinal();
    extension_sorting->SetPageOrdinal(app1_->id(), first_page);
    EXPECT_EQ(0, extension_sorting->PageStringOrdinalAsInteger(first_page));

    last_page_ = first_page.CreateAfter();
    extension_sorting->SetPageOrdinal(app2_->id(), last_page_);
    EXPECT_EQ(1, extension_sorting->PageStringOrdinalAsInteger(last_page_));

    // Move the second app to create an empty page.
    extension_sorting->SetPageOrdinal(app2_->id(), first_page);
    EXPECT_EQ(0, extension_sorting->PageStringOrdinalAsInteger(first_page));
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Move the second app to a new empty page at the end, skipping over
    // the current empty page.
    last_page_ = last_page_.CreateAfter();
    extension_sorting->SetPageOrdinal(app2_->id(), last_page_);
    EXPECT_EQ(2, extension_sorting->PageStringOrdinalAsInteger(last_page_));
    EXPECT_TRUE(
        last_page_.Equals(extension_sorting->PageIntegerAsStringOrdinal(2)));
  }

 private:
  syncer::StringOrdinal last_page_;
};
TEST_F(ExtensionSortingKeepEmptyStringOrdinalPages,
       ExtensionSortingKeepEmptyStringOrdinalPages) {}

class ExtensionSortingMakesFillerOrdinals
    : public ExtensionSortingPreinstalledAppsBase {
 public:
  ExtensionSortingMakesFillerOrdinals() {}
  virtual ~ExtensionSortingMakesFillerOrdinals() {}

  virtual void Initialize() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    syncer::StringOrdinal first_page =
        syncer::StringOrdinal::CreateInitialOrdinal();
    extension_sorting->SetPageOrdinal(app1_->id(), first_page);
    EXPECT_EQ(0, extension_sorting->PageStringOrdinalAsInteger(first_page));
  }
  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Because the UI can add an unlimited number of empty pages without an app
    // on them, this test simulates dropping of an app on the 1st and 4th empty
    // pages (3rd and 6th pages by index) to ensure we don't crash and that
    // filler ordinals are created as needed. See: http://crbug.com/122214
    syncer::StringOrdinal page_three =
        extension_sorting->PageIntegerAsStringOrdinal(2);
    extension_sorting->SetPageOrdinal(app1_->id(), page_three);
    EXPECT_EQ(2, extension_sorting->PageStringOrdinalAsInteger(page_three));

    syncer::StringOrdinal page_six =
        extension_sorting->PageIntegerAsStringOrdinal(5);
    extension_sorting->SetPageOrdinal(app1_->id(), page_six);
    EXPECT_EQ(5, extension_sorting->PageStringOrdinalAsInteger(page_six));
  }
};
TEST_F(ExtensionSortingMakesFillerOrdinals,
       ExtensionSortingMakesFillerOrdinals) {}

class ExtensionSortingDefaultOrdinalsBase : public ExtensionSortingTest {
 public:
  ExtensionSortingDefaultOrdinalsBase() {}
  virtual ~ExtensionSortingDefaultOrdinalsBase() {}

  virtual void Initialize() OVERRIDE {
    app_ = CreateApp("app");

    InitDefaultOrdinals();
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    ExtensionSorting::AppOrdinalsMap& sorting_defaults =
        extension_sorting->default_ordinals_;
    sorting_defaults[app_->id()].page_ordinal = default_page_ordinal_;
    sorting_defaults[app_->id()].app_launch_ordinal =
        default_app_launch_ordinal_;

    SetupUserOrdinals();
    InstallApps();
  }

 protected:
  scoped_refptr<Extension> CreateApp(const std::string& name) {
    DictionaryValue simple_dict;
    simple_dict.SetString(keys::kVersion, "1.0.0.0");
    simple_dict.SetString(keys::kName, name);
    simple_dict.SetString(keys::kApp, "true");
    simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");

    std::string errors;
    scoped_refptr<Extension> app = Extension::Create(
        prefs_.temp_dir().AppendASCII(name), Manifest::EXTERNAL_PREF,
        simple_dict, Extension::NO_FLAGS, &errors);
    EXPECT_TRUE(app.get()) << errors;
    EXPECT_TRUE(Extension::IdIsValid(app->id()));
    return app;
  }

  void InitDefaultOrdinals() {
    default_page_ordinal_ =
        syncer::StringOrdinal::CreateInitialOrdinal().CreateAfter();
    default_app_launch_ordinal_ =
        syncer::StringOrdinal::CreateInitialOrdinal().CreateBefore();
  }

  virtual void SetupUserOrdinals() {}

  virtual void InstallApps() {
    prefs()->OnExtensionInstalled(app_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  syncer::StringOrdinal());
  }

  scoped_refptr<Extension> app_;
  syncer::StringOrdinal default_page_ordinal_;
  syncer::StringOrdinal default_app_launch_ordinal_;
};

// Tests that the app gets its default ordinals.
class ExtensionSortingDefaultOrdinals
    : public ExtensionSortingDefaultOrdinalsBase {
 public:
  ExtensionSortingDefaultOrdinals() {}
  virtual ~ExtensionSortingDefaultOrdinals() {}

  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(app_->id()).Equals(
        default_page_ordinal_));
    EXPECT_TRUE(extension_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
        default_app_launch_ordinal_));
  }
};
TEST_F(ExtensionSortingDefaultOrdinals,
       ExtensionSortingDefaultOrdinals) {}

// Tests that the default page ordinal is overridden by install page ordinal.
class ExtensionSortingDefaultOrdinalOverriddenByInstallPage
    : public ExtensionSortingDefaultOrdinalsBase {
 public:
  ExtensionSortingDefaultOrdinalOverriddenByInstallPage() {}
  virtual ~ExtensionSortingDefaultOrdinalOverriddenByInstallPage() {}

  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    EXPECT_FALSE(extension_sorting->GetPageOrdinal(app_->id()).Equals(
        default_page_ordinal_));
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(app_->id()).Equals(
        install_page_));
  }

 protected:
  virtual void InstallApps() OVERRIDE {
    install_page_ = default_page_ordinal_.CreateAfter();
    prefs()->OnExtensionInstalled(app_.get(),
                                  Extension::ENABLED,
                                  Blacklist::NOT_BLACKLISTED,
                                  install_page_);
  }

 private:
  syncer::StringOrdinal install_page_;
};
TEST_F(ExtensionSortingDefaultOrdinalOverriddenByInstallPage,
       ExtensionSortingDefaultOrdinalOverriddenByInstallPage) {}

// Tests that the default ordinals are overridden by user values.
class ExtensionSortingDefaultOrdinalOverriddenByUserValue
    : public ExtensionSortingDefaultOrdinalsBase {
 public:
  ExtensionSortingDefaultOrdinalOverriddenByUserValue() {}
  virtual ~ExtensionSortingDefaultOrdinalOverriddenByUserValue() {}

  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    EXPECT_TRUE(extension_sorting->GetPageOrdinal(app_->id()).Equals(
        user_page_ordinal_));
    EXPECT_TRUE(extension_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
        user_app_launch_ordinal_));
  }

 protected:
  virtual void SetupUserOrdinals() OVERRIDE {
    user_page_ordinal_ = default_page_ordinal_.CreateAfter();
    user_app_launch_ordinal_ = default_app_launch_ordinal_.CreateBefore();

    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    extension_sorting->SetPageOrdinal(app_->id(), user_page_ordinal_);
    extension_sorting->SetAppLaunchOrdinal(app_->id(),
                                           user_app_launch_ordinal_);
  }

 private:
  syncer::StringOrdinal user_page_ordinal_;
  syncer::StringOrdinal user_app_launch_ordinal_;
};
TEST_F(ExtensionSortingDefaultOrdinalOverriddenByUserValue,
       ExtensionSortingDefaultOrdinalOverriddenByUserValue) {}

// Tests that the default app launch ordinal is changed to avoid collision.
class ExtensionSortingDefaultOrdinalNoCollision
    : public ExtensionSortingDefaultOrdinalsBase {
 public:
  ExtensionSortingDefaultOrdinalNoCollision() {}
  virtual ~ExtensionSortingDefaultOrdinalNoCollision() {}

  virtual void Verify() OVERRIDE {
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();

    // Use the default page.
    EXPECT_TRUE(extension_sorting->GetPageOrdinal(app_->id()).Equals(
        default_page_ordinal_));
    // Not using the default app launch ordinal because of the collision.
    EXPECT_FALSE(extension_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
        default_app_launch_ordinal_));
  }

 protected:
  virtual void SetupUserOrdinals() OVERRIDE {
    other_app_ = prefs_.AddApp("other_app");
    // Creates a collision.
    ExtensionSorting* extension_sorting = prefs()->extension_sorting();
    extension_sorting->SetPageOrdinal(other_app_->id(), default_page_ordinal_);
    extension_sorting->SetAppLaunchOrdinal(other_app_->id(),
                                           default_app_launch_ordinal_);

    yet_another_app_ = prefs_.AddApp("yet_aother_app");
    extension_sorting->SetPageOrdinal(yet_another_app_->id(),
                                      default_page_ordinal_);
    extension_sorting->SetAppLaunchOrdinal(yet_another_app_->id(),
                                           default_app_launch_ordinal_);
  }

 private:
  scoped_refptr<Extension> other_app_;
  scoped_refptr<Extension> yet_another_app_;
};
TEST_F(ExtensionSortingDefaultOrdinalNoCollision,
       ExtensionSortingDefaultOrdinalNoCollision) {}
