<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "tests/test-utils.hh"

#include <seastar/core/thread.hh>

#include "cell_locking.hh"
#include "mutation.hh"
#include "schema_builder.hh"

static schema_ptr make_schema()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s1", bytes_type, column_kind::static_column)
            .with_column("s2", bytes_type, column_kind::static_column)
            .with_column("s3", bytes_type, column_kind::static_column)
            .with_column("r1", bytes_type)
            .with_column("r2", bytes_type)
            .with_column("r3", bytes_type)
            .build();
}

static schema_ptr make_alternative_schema()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s0", bytes_type, column_kind::static_column)
            .with_column("s1", bytes_type, column_kind::static_column)
            .with_column("s2.5", bytes_type, column_kind::static_column)
            .with_column("s3", bytes_type, column_kind::static_column)
            .with_column("r0", bytes_type)
            .with_column("r1", bytes_type)
            .with_column("r2.5", bytes_type)
            .with_column("r3", bytes_type)
            .build();
}

static schema_ptr make_schema_disjoint_with_others()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s8", bytes_type, column_kind::static_column)
            .with_column("s9", bytes_type, column_kind::static_column)
            .with_column("r8", bytes_type)
            .with_column("r9", bytes_type)
            .build();
}

static data_value empty_value = data_value(to_bytes(""));

static db::timeout_clock::time_point no_timeout {
    db::timeout_clock::duration(std::numeric_limits<db::timeout_clock::duration::rep>::max())
};

static auto make_row(const sstring& key, std::initializer_list<sstring> cells) {
    return std::pair<sstring, std::initializer_list<sstring>>(key, cells);
}

static mutation make_mutation(schema_ptr s, const sstring& pk, std::initializer_list<sstring> static_cells,
                              std::initializer_list<std::pair<sstring, std::initializer_list<sstring>>> clustering_cells)
{
    auto m = mutation(s, partition_key::from_single_value(*s, to_bytes(pk)));
    for (auto&& c : static_cells) {
        m.set_static_cell(to_bytes(c), empty_value, api::new_timestamp());
    }
    for (auto&& r : clustering_cells) {
        auto ck = clustering_key::from_single_value(*s, to_bytes(r.first));
        for (auto&& c : r.second) {
            m.set_clustered_cell(ck, to_bytes(c), empty_value, api::new_timestamp());
        }
    }
    return m;
}

SEASTAR_TEST_CASE(test_simple_locking_cells) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m = make_mutation(s, "0", { "s1", "s3" }, {
            make_row("one", { "r1", "r2" }),
            make_row("two", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m.decorated_key(), partition_cells_range(m.partition()), no_timeout).get0();
        auto f2 = cl.lock_cells(m.decorated_key(), partition_cells_range(m.partition()), no_timeout);
        BOOST_REQUIRE(!f2.available());

        destroy(std::move(l1));
        destroy(f2.get0());
    });
}

SEASTAR_TEST_CASE(test_disjoint_mutations) {
    return seastar::async([&] {
        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s1" }, {
                make_row("one", { "r1", "r2" }),
                make_row("two", { "r3" }),
        });
        auto m2 = make_mutation(s, "0", { "s2" }, {
                make_row("two", { "r1", "r2" }),
                make_row("one", { "r3" }),
        });

        auto m3 = mutation(s, partition_key::from_single_value(*s, to_bytes("1")));
        m3.partition() = m1.partition();

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        auto l2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout).get0();
        auto l3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout).get0();
    });
}

SEASTAR_TEST_CASE(test_single_cell_overlap) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s1" }, {
                make_row("one", { "r1", "r2" }),
                make_row("two", { "r3" }),
        });
        auto m2 = make_mutation(s, "0", { "s1" }, {
                make_row("two", { "r1", "r2" }),
                make_row("one", { "r3" }),
        });
        auto m3 = make_mutation(s, "0", { "s2" }, {
                make_row("two", { "r1" }),
                make_row("one", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
        BOOST_REQUIRE(!f2.available());
        destroy(std::move(l1));
        auto l2 = f2.get0();
        auto f3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout);
        BOOST_REQUIRE(!f3.available());
        destroy(std::move(l2));
        auto l3 = f3.get0();
    });
}

SEASTAR_TEST_CASE(test_schema_change) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s1 = make_schema();
        auto s2 = make_alternative_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s1, cl_stats);

        auto m1 = make_mutation(s1, "0", { "s1", "s2", "s3"}, {
            make_row("one", { "r1", "r2", "r3" }),
        });

        // disjoint with m1
        auto m2 = make_mutation(s2, "0", { "s0", "s2.5"}, {
                make_row("one", { "r0", "r2.5" }),
                make_row("two", { "r1", "r3" }),
        });

        // overlaps with m1
        auto m3 = make_mutation(s2, "0", { "s1" }, {
                make_row("one", { "r1", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();

        destroy(std::move(m1));
        destroy(std::move(s1));
        cl.set_schema(s2);

        auto l2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout).get0();
        auto f3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout);
        BOOST_REQUIRE(!f3.available());
        destroy(std::move(l1));
        auto l3 = f3.get0();

        auto s3 = make_schema_disjoint_with_others();
        cl.set_schema(s3);

        auto m4 = make_mutation(s3, "0", { "s8", "s9"}, {
                make_row("one", { "r8", "r9" }),
                make_row("two", { "r8", "r9" }),
        });
        auto l4 = cl.lock_cells(m4.decorated_key(), partition_cells_range(m4.partition()), no_timeout).get0();
    });
}

SEASTAR_TEST_CASE(test_timed_out) {
        return seastar::async([&] {
            auto destroy = [] (auto) { };

            auto s = make_schema();
            cell_locker_stats cl_stats;
            cell_locker cl(s, cl_stats);

            auto m1 = make_mutation(s, "0", { "s1", "s2", "s3"}, {
                    make_row("one", { "r2", "r3" }),
            });
            auto m2 = make_mutation(s, "0", { }, {
                    make_row("one", { "r1", "r2" }),
            });

            auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();

            auto timeout = db::timeout_clock::now() - std::chrono::hours(1);
            BOOST_REQUIRE_THROW(cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), timeout).get0(),
                                timed_out_error);

            auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
            BOOST_REQUIRE(!f2.available());
            destroy(std::move(l1));
            auto l2 = f2.get0();
        });
}

SEASTAR_TEST_CASE(test_locker_stats) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s2", "s3" }, {
                make_row("one", { "r1", "r2" }),
        });

        auto m2 = make_mutation(s, "0", { "s1", "s3" }, {
                make_row("one", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 4);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 0);

        auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 5);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 1);
        BOOST_REQUIRE(!f2.available());

        destroy(std::move(l1));
        destroy(f2.get0());
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 8);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 0);
    });
}
<commit_msg>tests/cell_locker_test: Ensure timeout test finishes in useful time<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "tests/test-utils.hh"

#include <seastar/core/thread.hh>

#include "cell_locking.hh"
#include "mutation.hh"
#include "schema_builder.hh"

static schema_ptr make_schema()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s1", bytes_type, column_kind::static_column)
            .with_column("s2", bytes_type, column_kind::static_column)
            .with_column("s3", bytes_type, column_kind::static_column)
            .with_column("r1", bytes_type)
            .with_column("r2", bytes_type)
            .with_column("r3", bytes_type)
            .build();
}

static schema_ptr make_alternative_schema()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s0", bytes_type, column_kind::static_column)
            .with_column("s1", bytes_type, column_kind::static_column)
            .with_column("s2.5", bytes_type, column_kind::static_column)
            .with_column("s3", bytes_type, column_kind::static_column)
            .with_column("r0", bytes_type)
            .with_column("r1", bytes_type)
            .with_column("r2.5", bytes_type)
            .with_column("r3", bytes_type)
            .build();
}

static schema_ptr make_schema_disjoint_with_others()
{
    return schema_builder("ks", "cf")
            .with_column("pk", bytes_type, column_kind::partition_key)
            .with_column("ck", bytes_type, column_kind::clustering_key)
            .with_column("s8", bytes_type, column_kind::static_column)
            .with_column("s9", bytes_type, column_kind::static_column)
            .with_column("r8", bytes_type)
            .with_column("r9", bytes_type)
            .build();
}

static data_value empty_value = data_value(to_bytes(""));

static db::timeout_clock::time_point no_timeout {
    db::timeout_clock::duration(std::numeric_limits<db::timeout_clock::duration::rep>::max())
};

static auto make_row(const sstring& key, std::initializer_list<sstring> cells) {
    return std::pair<sstring, std::initializer_list<sstring>>(key, cells);
}

static mutation make_mutation(schema_ptr s, const sstring& pk, std::initializer_list<sstring> static_cells,
                              std::initializer_list<std::pair<sstring, std::initializer_list<sstring>>> clustering_cells)
{
    auto m = mutation(s, partition_key::from_single_value(*s, to_bytes(pk)));
    for (auto&& c : static_cells) {
        m.set_static_cell(to_bytes(c), empty_value, api::new_timestamp());
    }
    for (auto&& r : clustering_cells) {
        auto ck = clustering_key::from_single_value(*s, to_bytes(r.first));
        for (auto&& c : r.second) {
            m.set_clustered_cell(ck, to_bytes(c), empty_value, api::new_timestamp());
        }
    }
    return m;
}

SEASTAR_TEST_CASE(test_simple_locking_cells) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m = make_mutation(s, "0", { "s1", "s3" }, {
            make_row("one", { "r1", "r2" }),
            make_row("two", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m.decorated_key(), partition_cells_range(m.partition()), no_timeout).get0();
        auto f2 = cl.lock_cells(m.decorated_key(), partition_cells_range(m.partition()), no_timeout);
        BOOST_REQUIRE(!f2.available());

        destroy(std::move(l1));
        destroy(f2.get0());
    });
}

SEASTAR_TEST_CASE(test_disjoint_mutations) {
    return seastar::async([&] {
        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s1" }, {
                make_row("one", { "r1", "r2" }),
                make_row("two", { "r3" }),
        });
        auto m2 = make_mutation(s, "0", { "s2" }, {
                make_row("two", { "r1", "r2" }),
                make_row("one", { "r3" }),
        });

        auto m3 = mutation(s, partition_key::from_single_value(*s, to_bytes("1")));
        m3.partition() = m1.partition();

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        auto l2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout).get0();
        auto l3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout).get0();
    });
}

SEASTAR_TEST_CASE(test_single_cell_overlap) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s1" }, {
                make_row("one", { "r1", "r2" }),
                make_row("two", { "r3" }),
        });
        auto m2 = make_mutation(s, "0", { "s1" }, {
                make_row("two", { "r1", "r2" }),
                make_row("one", { "r3" }),
        });
        auto m3 = make_mutation(s, "0", { "s2" }, {
                make_row("two", { "r1" }),
                make_row("one", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
        BOOST_REQUIRE(!f2.available());
        destroy(std::move(l1));
        auto l2 = f2.get0();
        auto f3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout);
        BOOST_REQUIRE(!f3.available());
        destroy(std::move(l2));
        auto l3 = f3.get0();
    });
}

SEASTAR_TEST_CASE(test_schema_change) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s1 = make_schema();
        auto s2 = make_alternative_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s1, cl_stats);

        auto m1 = make_mutation(s1, "0", { "s1", "s2", "s3"}, {
            make_row("one", { "r1", "r2", "r3" }),
        });

        // disjoint with m1
        auto m2 = make_mutation(s2, "0", { "s0", "s2.5"}, {
                make_row("one", { "r0", "r2.5" }),
                make_row("two", { "r1", "r3" }),
        });

        // overlaps with m1
        auto m3 = make_mutation(s2, "0", { "s1" }, {
                make_row("one", { "r1", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();

        destroy(std::move(m1));
        destroy(std::move(s1));
        cl.set_schema(s2);

        auto l2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout).get0();
        auto f3 = cl.lock_cells(m3.decorated_key(), partition_cells_range(m3.partition()), no_timeout);
        BOOST_REQUIRE(!f3.available());
        destroy(std::move(l1));
        auto l3 = f3.get0();

        auto s3 = make_schema_disjoint_with_others();
        cl.set_schema(s3);

        auto m4 = make_mutation(s3, "0", { "s8", "s9"}, {
                make_row("one", { "r8", "r9" }),
                make_row("two", { "r8", "r9" }),
        });
        auto l4 = cl.lock_cells(m4.decorated_key(), partition_cells_range(m4.partition()), no_timeout).get0();
    });
}

SEASTAR_TEST_CASE(test_timed_out) {
        return seastar::async([&] {
            auto destroy = [] (auto) { };

            auto s = make_schema();
            cell_locker_stats cl_stats;
            cell_locker cl(s, cl_stats);

            auto m1 = make_mutation(s, "0", { "s1", "s2", "s3"}, {
                    make_row("one", { "r2", "r3" }),
            });
            auto m2 = make_mutation(s, "0", { }, {
                    make_row("one", { "r1", "r2" }),
            });

            auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();

            auto timeout = saturating_subtract(db::timeout_clock::now(), std::chrono::hours(1));
            BOOST_REQUIRE_THROW(cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), timeout).get0(),
                                timed_out_error);

            auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
            BOOST_REQUIRE(!f2.available());
            destroy(std::move(l1));
            auto l2 = f2.get0();
        });
}

SEASTAR_TEST_CASE(test_locker_stats) {
    return seastar::async([&] {
        auto destroy = [] (auto) { };

        auto s = make_schema();
        cell_locker_stats cl_stats;
        cell_locker cl(s, cl_stats);

        auto m1 = make_mutation(s, "0", { "s2", "s3" }, {
                make_row("one", { "r1", "r2" }),
        });

        auto m2 = make_mutation(s, "0", { "s1", "s3" }, {
                make_row("one", { "r2", "r3" }),
        });

        auto l1 = cl.lock_cells(m1.decorated_key(), partition_cells_range(m1.partition()), no_timeout).get0();
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 4);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 0);

        auto f2 = cl.lock_cells(m2.decorated_key(), partition_cells_range(m2.partition()), no_timeout);
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 5);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 1);
        BOOST_REQUIRE(!f2.available());

        destroy(std::move(l1));
        destroy(f2.get0());
        BOOST_REQUIRE_EQUAL(cl_stats.lock_acquisitions, 8);
        BOOST_REQUIRE_EQUAL(cl_stats.operations_waiting_for_lock, 0);
    });
}
<|endoftext|>


<commit_before>// 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/profiles/profile_info_util.h"

#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia_operations.h"

// Helper methods for transforming and drawing avatar icons.
namespace {

// Given a width, determine the height that preserves the aspect ratio.
int GetAvatarHeightByRatio(int width) {

  // Multiply the desired width by the aspect ratio to determine the
  // desired height. Add 0.5 before int truncating to ensure proper rounding.
  int ideal_height_for_width =
      (width * profiles::kAvatarIconHeight / profiles::kAvatarIconWidth) +
      0.5f;
  return ideal_height_for_width;
}

// A CanvasImageSource that draws a sized and positioned avatar with an
// optional border independently of the scale factor.
class AvatarImageSource : public gfx::CanvasImageSource {
 public:
  enum AvatarPosition {
    POSITION_CENTER,
    POSITION_BOTTOM_CENTER,
  };

  enum AvatarBorder {
    BORDER_NONE,
    BORDER_NORMAL,
    BORDER_ETCHED,
  };

  AvatarImageSource(gfx::ImageSkia avatar,
                    const gfx::Size& canvas_size,
                    int size,
                    AvatarPosition position,
                    AvatarBorder border);
  virtual ~AvatarImageSource();

  // CanvasImageSource override:
  virtual void Draw(gfx::Canvas* canvas) OVERRIDE;

 private:
  gfx::ImageSkia avatar_;
  const gfx::Size canvas_size_;
  const int size_;
  const AvatarPosition position_;
  const AvatarBorder border_;

  DISALLOW_COPY_AND_ASSIGN(AvatarImageSource);
};

AvatarImageSource::AvatarImageSource(gfx::ImageSkia avatar,
                                     const gfx::Size& canvas_size,
                                     int size,
                                     AvatarPosition position,
                                     AvatarBorder border)
    : gfx::CanvasImageSource(canvas_size, false),
      canvas_size_(canvas_size),
      size_(size - profiles::kAvatarIconPadding),
      position_(position),
      border_(border) {
  // Resize the avatar to the desired square size, avoiding stretches.
  int resized_avatar_height = GetAvatarHeightByRatio(size_);
  avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
      avatar, skia::ImageOperations::RESIZE_BEST,
      gfx::Size(size_, resized_avatar_height));
}

AvatarImageSource::~AvatarImageSource() {
}

void AvatarImageSource::Draw(gfx::Canvas* canvas) {
  // Center the avatar horizontally.
  int x = (canvas_size_.width() - size_) / 2;
  int y;
  float extra_height = 0.0f;

  if (position_ == POSITION_CENTER) {
    // Draw the avatar centered on the canvas.
    y = (canvas_size_.height() - size_) / 2;

    // The avatar may be shorter than it is wide, rather than perfectly square
    // If so, center it further down than otherwise.
    extra_height = (size_ - GetAvatarHeightByRatio(size_)) / 2.0f;
  } else {
    // Draw the avatar on the bottom center of the canvas, leaving 1px below.
    y = canvas_size_.height() - size_ - 1;
  }

  canvas->DrawImageInt(avatar_, x, y + extra_height);

  if (border_ == BORDER_NORMAL) {
    // Draw a gray border on the inside of the avatar.
    SkColor border_color = SkColorSetARGB(83, 0, 0, 0);

    // Offset the rectangle by a half pixel so the border is drawn within the
    // appropriate pixels no matter the scale factor. Subtract 1 from the right
    // and bottom sizes to specify the endpoints, yielding -0.5.
    SkPath path;
    path.addRect(SkFloatToScalar(x + 0.5f),  // left
                 SkFloatToScalar(y + 0.5f),  // top
                 SkFloatToScalar(x + size_ - 0.5f),   // right
                 SkFloatToScalar(y + size_ - 0.5f));  // bottom

    SkPaint paint;
    paint.setColor(border_color);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(SkIntToScalar(1));

    canvas->DrawPath(path, paint);
  } else if (border_ == BORDER_ETCHED) {
    // Give the avatar an etched look by drawing a highlight on the bottom and
    // right edges.
    SkColor shadow_color = SkColorSetARGB(83, 0, 0, 0);
    SkColor highlight_color = SkColorSetARGB(96, 255, 255, 255);

    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(SkIntToScalar(1));

    SkPath path;

    // Left and top shadows. To support higher scale factors than 1, position
    // the orthogonal dimension of each line on the half-pixel to separate the
    // pixel. For a vertical line, this means adding 0.5 to the x-value.
    path.moveTo(SkFloatToScalar(x + 0.5f), SkIntToScalar(y + size_));

    // Draw up to the top-left. Stop with the y-value at a half-pixel.
    path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-size_ + 0.5f));

    // Draw right to the top-right, stopping within the last pixel.
    path.rLineTo(SkFloatToScalar(size_ - 0.5f), SkIntToScalar(0));

    paint.setColor(shadow_color);
    canvas->DrawPath(path, paint);

    path.reset();

    // Bottom and right highlights. Note that the shadows own the shared corner
    // pixels, so reduce the sizes accordingly.
    path.moveTo(SkIntToScalar(x + 1), SkFloatToScalar(y + size_ - 0.5f));

    // Draw right to the bottom-right.
    path.rLineTo(SkFloatToScalar(size_ - 1.5f), SkIntToScalar(0));

    // Draw up to the top-right.
    path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-size_ + 1.5f));

    paint.setColor(highlight_color);
    canvas->DrawPath(path, paint);
  }
}

}  // namespace

namespace profiles {

const int kAvatarIconWidth = 38;
const int kAvatarIconHeight = 31;
const int kAvatarIconPadding = 2;

gfx::Image GetSizedAvatarIconWithBorder(const gfx::Image& image,
                                        bool is_rectangle,
                                        int width, int height) {
  if (!is_rectangle)
    return image;

  gfx::Size size(width, height);

  // Source for a centered, sized icon with a border.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          size,
          std::min(width, height),
          AvatarImageSource::POSITION_CENTER,
          AvatarImageSource::BORDER_NORMAL));

  return gfx::Image(gfx::ImageSkia(source.release(), size));
}

gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
                                bool is_rectangle) {
  return GetSizedAvatarIconWithBorder(
      image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight);
}

gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
                                 bool is_rectangle) {
  if (!is_rectangle)
    return image;

  gfx::Size size(kAvatarIconWidth, kAvatarIconHeight);

  // Source for a centered, sized icon.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          size,
          std::min(kAvatarIconWidth, kAvatarIconHeight),
          AvatarImageSource::POSITION_CENTER,
          AvatarImageSource::BORDER_NONE));

  return gfx::Image(gfx::ImageSkia(source.release(), size));
}

gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
                                    bool is_rectangle,
                                    int dst_width,
                                    int dst_height) {
  if (!is_rectangle)
    return image;

  int size = std::min(std::min(kAvatarIconWidth, kAvatarIconHeight),
                      std::min(dst_width, dst_height));
  gfx::Size dst_size(dst_width, dst_height);

  // Source for a sized icon drawn at the bottom center of the canvas,
  // with an etched border.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          dst_size,
          size,
          AvatarImageSource::POSITION_BOTTOM_CENTER,
          AvatarImageSource::BORDER_ETCHED));

  return gfx::Image(gfx::ImageSkia(source.release(), dst_size));
}

}  // namespace profiles
<commit_msg>Any avatar icon should now display well, both cartoons and account photos.<commit_after>// 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/profiles/profile_info_util.h"

#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia_operations.h"

// Helper methods for transforming and drawing avatar icons.
namespace {

// Determine what the scaled height of the avatar icon should be for a
// specified width, to preserve the aspect ratio.
int GetScaledAvatarHeightForWidth(int width, const gfx::ImageSkia& avatar) {

  // Multiply the width by the inverted aspect ratio (height over
  // width), and then add 0.5 to ensure the int truncation rounds nicely.
  int scaled_height = width *
      ((float) avatar.height() / (float) avatar.width()) + 0.5f;
  return scaled_height;
}

// A CanvasImageSource that draws a sized and positioned avatar with an
// optional border independently of the scale factor.
class AvatarImageSource : public gfx::CanvasImageSource {
 public:
  enum AvatarPosition {
    POSITION_CENTER,
    POSITION_BOTTOM_CENTER,
  };

  enum AvatarBorder {
    BORDER_NONE,
    BORDER_NORMAL,
    BORDER_ETCHED,
  };

  AvatarImageSource(gfx::ImageSkia avatar,
                    const gfx::Size& canvas_size,
                    int width,
                    AvatarPosition position,
                    AvatarBorder border);
  virtual ~AvatarImageSource();

  // CanvasImageSource override:
  virtual void Draw(gfx::Canvas* canvas) OVERRIDE;

 private:
  gfx::ImageSkia avatar_;
  const gfx::Size canvas_size_;
  const int width_;
  const int height_;
  const AvatarPosition position_;
  const AvatarBorder border_;

  DISALLOW_COPY_AND_ASSIGN(AvatarImageSource);
};

AvatarImageSource::AvatarImageSource(gfx::ImageSkia avatar,
                                     const gfx::Size& canvas_size,
                                     int width,
                                     AvatarPosition position,
                                     AvatarBorder border)
    : gfx::CanvasImageSource(canvas_size, false),
      canvas_size_(canvas_size),
      width_(width - profiles::kAvatarIconPadding),
      height_(GetScaledAvatarHeightForWidth(width, avatar) -
          profiles::kAvatarIconPadding),
      position_(position),
      border_(border) {
  avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
      avatar, skia::ImageOperations::RESIZE_BEST,
      gfx::Size(width_, height_));
}

AvatarImageSource::~AvatarImageSource() {
}

void AvatarImageSource::Draw(gfx::Canvas* canvas) {
  // Center the avatar horizontally.
  int x = (canvas_size_.width() - width_) / 2;
  int y;

  if (position_ == POSITION_CENTER) {
    // Draw the avatar centered on the canvas.
    y = (canvas_size_.height() - height_) / 2;
  } else {
    // Draw the avatar on the bottom center of the canvas, leaving 1px below.
    y = canvas_size_.height() - height_ - 1;
  }

  canvas->DrawImageInt(avatar_, x, y);

  // The border should be square.
  int border_size = std::max(width_, height_);
  // Reset the x and y for the square border.
  x = (canvas_size_.width() - border_size) / 2;
  y = (canvas_size_.height() - border_size) / 2;

  if (border_ == BORDER_NORMAL) {
    // Draw a gray border on the inside of the avatar.
    SkColor border_color = SkColorSetARGB(83, 0, 0, 0);

    // Offset the rectangle by a half pixel so the border is drawn within the
    // appropriate pixels no matter the scale factor. Subtract 1 from the right
    // and bottom sizes to specify the endpoints, yielding -0.5.
    SkPath path;
    path.addRect(SkFloatToScalar(x + 0.5f),  // left
                 SkFloatToScalar(y + 0.5f),  // top
                 SkFloatToScalar(x + border_size - 0.5f),   // right
                 SkFloatToScalar(y + border_size - 0.5f));  // bottom

    SkPaint paint;
    paint.setColor(border_color);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(SkIntToScalar(1));

    canvas->DrawPath(path, paint);
  } else if (border_ == BORDER_ETCHED) {
    // Give the avatar an etched look by drawing a highlight on the bottom and
    // right edges.
    SkColor shadow_color = SkColorSetARGB(83, 0, 0, 0);
    SkColor highlight_color = SkColorSetARGB(96, 255, 255, 255);

    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(SkIntToScalar(1));

    SkPath path;

    // Left and top shadows. To support higher scale factors than 1, position
    // the orthogonal dimension of each line on the half-pixel to separate the
    // pixel. For a vertical line, this means adding 0.5 to the x-value.
    path.moveTo(SkFloatToScalar(x + 0.5f), SkIntToScalar(y + height_));

    // Draw up to the top-left. Stop with the y-value at a half-pixel.
    path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-height_ + 0.5f));

    // Draw right to the top-right, stopping within the last pixel.
    path.rLineTo(SkFloatToScalar(width_ - 0.5f), SkIntToScalar(0));

    paint.setColor(shadow_color);
    canvas->DrawPath(path, paint);

    path.reset();

    // Bottom and right highlights. Note that the shadows own the shared corner
    // pixels, so reduce the sizes accordingly.
    path.moveTo(SkIntToScalar(x + 1), SkFloatToScalar(y + height_ - 0.5f));

    // Draw right to the bottom-right.
    path.rLineTo(SkFloatToScalar(width_ - 1.5f), SkIntToScalar(0));

    // Draw up to the top-right.
    path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-height_ + 1.5f));

    paint.setColor(highlight_color);
    canvas->DrawPath(path, paint);
  }
}

}  // namespace

namespace profiles {

const int kAvatarIconWidth = 38;
const int kAvatarIconHeight = 31;
const int kAvatarIconPadding = 2;

gfx::Image GetSizedAvatarIconWithBorder(const gfx::Image& image,
                                        bool is_rectangle,
                                        int width, int height) {
  if (!is_rectangle)
    return image;

  gfx::Size size(width, height);

  // Source for a centered, sized icon with a border.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          size,
          std::min(width, height),
          AvatarImageSource::POSITION_CENTER,
          AvatarImageSource::BORDER_NORMAL));

  return gfx::Image(gfx::ImageSkia(source.release(), size));
}

gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
                                bool is_rectangle) {
  return GetSizedAvatarIconWithBorder(
      image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight);
}

gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
                                 bool is_rectangle) {
  if (!is_rectangle)
    return image;

  gfx::Size size(kAvatarIconWidth, kAvatarIconHeight);

  // Source for a centered, sized icon.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          size,
          std::min(kAvatarIconWidth, kAvatarIconHeight),
          AvatarImageSource::POSITION_CENTER,
          AvatarImageSource::BORDER_NONE));

  return gfx::Image(gfx::ImageSkia(source.release(), size));
}

gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
                                    bool is_rectangle,
                                    int dst_width,
                                    int dst_height) {
  if (!is_rectangle)
    return image;

  int size = std::min(std::min(kAvatarIconWidth, kAvatarIconHeight),
                      std::min(dst_width, dst_height));
  gfx::Size dst_size(dst_width, dst_height);

  // Source for a sized icon drawn at the bottom center of the canvas,
  // with an etched border.
  scoped_ptr<gfx::ImageSkiaSource> source(
      new AvatarImageSource(
          *image.ToImageSkia(),
          dst_size,
          size,
          AvatarImageSource::POSITION_BOTTOM_CENTER,
          AvatarImageSource::BORDER_ETCHED));

  return gfx::Image(gfx::ImageSkia(source.release(), dst_size));
}

}  // namespace profiles
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "ROOT/THist.hxx"

#include <atomic>
#include <vector>

/** Basic tests for histograms of integral precision using vector<atomic> storage.
   NOTE that floating point precision is not supported - it would need a hand-written
   fetch_add implementation or the arrival of P0020 in C++. */

using namespace ROOT::Experimental;

// Storage using vector<atomic<>>
template <class PRECISION>
using atomicvec_t = std::vector<std::atomic<PRECISION>>;

// A THistData using vector<atomic<>> as storage.
template <int DIM, class PRECISION>
using atomic_histdata_t = Detail::THistData<DIM, PRECISION, atomicvec_t, THistStatContent>;

// THistImpl uses op+= to add to bin content; provide the relevant overload.
template <class INTEGRAL, class = decltype(std::declval<std::atomic<INTEGRAL>>().fetch_add(INTEGRAL()))>
std::atomic<INTEGRAL> &operator+=(std::atomic<INTEGRAL> &lhs, INTEGRAL rhs)
{
   lhs.fetch_add(rhs);
   return lhs;
}

// Test creation of THistImpl with atomic precision.
TEST(HistAtomicPrecisionTest, Create)
{
   Detail::THistImpl<atomic_histdata_t<1, int>, TAxisEquidistant> h1I(TAxisEquidistant{100, 0., 1});
   Detail::THistImpl<atomic_histdata_t<2, char>, TAxisEquidistant, TAxisEquidistant> h2C(TAxisEquidistant{100, 0., 1},
                                                                                TAxisEquidistant{10, -1., 1});
   Detail::THistImpl<atomic_histdata_t<1, long long>, TAxisIrregular> h1LLIrr(TAxisIrregular{{0., 0.1, 0.5, 1}});
}

// Test filling of THistImpl with atomic precision.
TEST(HistAtomicPrecisionTest, Fill1Int)
{
   Detail::THistImpl<atomic_histdata_t<1, int>, TAxisEquidistant> h1I(TAxisEquidistant{100, 0., 1});
   h1I.Fill({0.2222}, 12);
   EXPECT_EQ(12, h1I.GetBinContent({0.2222}));
}

TEST(HistAtomicPrecisionTest, Fill2LongLong)
{
   Detail::THistImpl<atomic_histdata_t<2, long long>, TAxisEquidistant, TAxisEquidistant> hist(
      TAxisEquidistant{100, 0., 1}, TAxisEquidistant{10, -1., 1});
   hist.Fill({0.1111, -0.2222}, 42ll);
   EXPECT_EQ(42ll, hist.GetBinContent({0.1111, -0.2222}));
}

TEST(HistAtomicPrecisionTest, Fill1CharIrr)
{
   Detail::THistImpl<atomic_histdata_t<1, char>, TAxisIrregular> hist(TAxisIrregular{{0., 0.1, 0.5, 1}});
   hist.Fill({0.1111}, 17);
   EXPECT_EQ(17, hist.GetBinContent({0.1111}));
}
<commit_msg>Add test for THistImpl with vector<atomic<FLOAT>>.<commit_after>#include "gtest/gtest.h"

#include "ROOT/THist.hxx"

#include <atomic>
#include <vector>

/** Basic tests for histograms of integral precision using vector<atomic> storage.
   */

using namespace ROOT::Experimental;

// Implementation of op+= for integral.
template <class INTEGRAL>
std::atomic<INTEGRAL> &atomic_addeq(std::atomic<INTEGRAL> &lhs, INTEGRAL rhs,
                                    decltype(std::declval<std::atomic<INTEGRAL>>().fetch_add(INTEGRAL())) * = nullptr)
{
   lhs.fetch_add(rhs);
   return lhs;
}

// Implementation of op+= for floats.
template <class FLOAT>
std::atomic<FLOAT> &atomic_addeq(std::atomic<FLOAT> &lhs, FLOAT rhs,
                                 typename std::enable_if<std::is_floating_point<FLOAT>::value>::type * = nullptr)
{
   auto oldval = lhs.load(std::memory_order_relaxed);
   auto newval = oldval + rhs;
   while (lhs.compare_exchange_strong(oldval, newval)) {
      // oldval is changed to what bin holds at the call to compare_exchange_strong
      newval = oldval + rhs;
   }
   return lhs;
}

// THistImpl uses op+= to add to bin content; provide the relevant overload.
template <class PRECISION>
std::atomic<PRECISION> &operator+=(std::atomic<PRECISION> &lhs, PRECISION rhs)
{
   return atomic_addeq(lhs, rhs);
}

// Storage using vector<atomic<>>
template <class PRECISION>
using atomicvec_t = std::vector<std::atomic<PRECISION>>;

// A THistData using vector<atomic<>> as storage.
template <int DIM, class PRECISION>
using content_t = Detail::THistData<DIM, PRECISION, atomicvec_t, THistStatContent>;

template <int DIM, class PRECISION>
using uncert_t = Detail::THistData<DIM, PRECISION, atomicvec_t, THistStatContent, THistStatUncertainty>;

// Test creation of THistImpl with atomic precision.
TEST(HistAtomicPrecisionTest, Create)
{
   Detail::THistImpl<content_t<1, int>, TAxisEquidistant> h1I(TAxisEquidistant{100, 0., 1});
   Detail::THistImpl<content_t<2, char>, TAxisEquidistant, TAxisEquidistant> h2C(TAxisEquidistant{100, 0., 1},
                                                                                TAxisEquidistant{10, -1., 1});
   Detail::THistImpl<content_t<1, long long>, TAxisIrregular> h1LLIrr(TAxisIrregular{{0., 0.1, 0.5, 1}});
   Detail::THistImpl<uncert_t<1, float>, TAxisEquidistant> h1F(TAxisEquidistant{100, 0., 1});
   Detail::THistImpl<uncert_t<1, double>, TAxisEquidistant> h1D(TAxisEquidistant{100, 0., 1});
}

// Test filling of THistImpl with atomic precision.
TEST(HistAtomicPrecisionTest, Fill1Int)
{
   Detail::THistImpl<content_t<1, int>, TAxisEquidistant> hist(TAxisEquidistant{100, 0., 1});
   hist.Fill({0.2222}, 12);
   EXPECT_EQ(12, hist.GetBinContent({0.2222}));
}

TEST(HistAtomicPrecisionTest, Fill2LongLong)
{
   Detail::THistImpl<content_t<2, long long>, TAxisEquidistant, TAxisEquidistant> hist(TAxisEquidistant{100, 0., 1},
                                                                                TAxisEquidistant{10, -1., 1});
   hist.Fill({0.1111, -0.2222}, 42ll);
   EXPECT_EQ(42ll, hist.GetBinContent({0.1111, -0.2222}));
}

TEST(HistAtomicPrecisionTest, Fill1CharIrr)
{
   Detail::THistImpl<content_t<1, char>, TAxisIrregular> hist(TAxisIrregular{{0., 0.1, 0.5, 1}});
   hist.Fill({0.1111}, 17);
   EXPECT_EQ(17, hist.GetBinContent({0.1111}));
}

TEST(HistAtomicPrecisionTest, Fill1Double)
{
   Detail::THistImpl<uncert_t<1, double>, TAxisEquidistant> hist(TAxisEquidistant{100, 0., 1});
   hist.Fill({0.2222}, 19.);
   EXPECT_DOUBLE_EQ(19., hist.GetBinContent({0.2222}));
}

TEST(HistAtomicPrecisionTest, Fill1Float)
{
   Detail::THistImpl<uncert_t<1, float>, TAxisEquidistant> hist(TAxisEquidistant{100, 0., 1});
   hist.Fill({0.9999}, -9.);
   EXPECT_FLOAT_EQ(-9., hist.GetBinContent({0.9999}));
   EXPECT_FLOAT_EQ(9., hist.GetBinUncertainty(hist.GetBinIndex({0.9999})));
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/automation/ui_controls.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
#include "chrome/browser/chromeos/cros/mock_input_method_library.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/screen_locker_tester.h"
#include "chrome/browser/chromeos/login/mock_authenticator.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/views/browser_dialogs.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "views/controls/textfield/textfield.h"
#include "views/window/window_gtk.h"

namespace {

// An object that wait for lock state and fullscreen state.
class Waiter : public NotificationObserver {
 public:
  Waiter(Browser* browser)
      : browser_(browser) {
    registrar_.Add(this,
                   NotificationType::SCREEN_LOCK_STATE_CHANGED,
                   NotificationService::AllSources());
    handler_id_ = g_signal_connect(
        G_OBJECT(browser_->window()->GetNativeHandle()),
        "window-state-event",
        G_CALLBACK(OnWindowStateEventThunk),
        this);
  }

  ~Waiter() {
    g_signal_handler_disconnect(
        G_OBJECT(browser_->window()->GetNativeHandle()),
        handler_id_);
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    DCHECK(type == NotificationType::SCREEN_LOCK_STATE_CHANGED);
    MessageLoop::current()->Quit();
  }

  // Wait until the two conditions are met.
  void Wait(bool locker_state, bool fullscreen) {
    scoped_ptr<chromeos::test::ScreenLockerTester>
        tester(chromeos::ScreenLocker::GetTester());
    while (tester->IsLocked() != locker_state ||
           browser_->window()->IsFullscreen() != fullscreen) {
      ui_test_utils::RunMessageLoop();
    }
    // Make sure all pending tasks are executed.
    ui_test_utils::RunAllPendingInMessageLoop();
  }

  CHROMEGTK_CALLBACK_1(Waiter, gboolean, OnWindowStateEvent,
                       GdkEventWindowState*);

 private:
  Browser* browser_;
  gulong handler_id_;
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(Waiter);
};

gboolean Waiter::OnWindowStateEvent(GtkWidget* widget,
                                    GdkEventWindowState* event) {
  MessageLoop::current()->Quit();
  return false;
}

}  // namespace

namespace chromeos {

class ScreenLockerTest : public CrosInProcessBrowserTest {
 public:
  ScreenLockerTest() {}

 protected:

  // Test the no password mode with different unlock scheme given by
  // |unlock| function.
  void TestNoPassword(void (unlock)(views::Widget*)) {
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested())
        .Times(1)
        .RetiresOnSaturation();
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
        .Times(1)
        .RetiresOnSaturation();
    UserManager::Get()->OffTheRecordUserLoggedIn();
    ScreenLocker::Show();
    scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
    tester->EmulateWindowManagerReady();
    ui_test_utils::WaitForNotification(
        NotificationType::SCREEN_LOCK_STATE_CHANGED);
    EXPECT_TRUE(tester->IsLocked());
    tester->InjectMockAuthenticator("", "");

    unlock(tester->GetWidget());

    ui_test_utils::RunAllPendingInMessageLoop();
    EXPECT_TRUE(tester->IsLocked());

    // Emulate LockScreen request from PowerManager (via SessionManager).
    ScreenLocker::Hide();
    ui_test_utils::RunAllPendingInMessageLoop();
    EXPECT_FALSE(tester->IsLocked());
  }

 private:
  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    InitMockScreenLockLibrary();
    EXPECT_CALL(*mock_screen_lock_library_, AddObserver(testing::_))
        .Times(1)
        .RetiresOnSaturation();
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockCompleted())
        .Times(1)
        .RetiresOnSaturation();
    // Expectations for the status are on the screen lock window.
    SetStatusAreaMocksExpectations();
    // Expectations for the status area on the browser window.
    SetStatusAreaMocksExpectations();
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitchWithValue(switches::kLoginProfile, "user");
    command_line->AppendSwitch(switches::kNoFirstRun);
  }

  DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest);
};

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) {
  EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods())
      .Times(1)
      .WillRepeatedly((testing::Return(0)))
      .RetiresOnSaturation();
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested())
      .Times(1)
      .RetiresOnSaturation();
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
      .Times(1)
      .RetiresOnSaturation();
  UserManager::Get()->UserLoggedIn("user");
  ScreenLocker::Show();
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  tester->EmulateWindowManagerReady();
  ui_test_utils::WaitForNotification(
      NotificationType::SCREEN_LOCK_STATE_CHANGED);

  tester->InjectMockAuthenticator("user", "pass");
  EXPECT_TRUE(tester->IsLocked());
  tester->EnterPassword("fail");
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_TRUE(tester->IsLocked());
  tester->EnterPassword("pass");
  ui_test_utils::RunAllPendingInMessageLoop();
  // Successful authentication simply send a unlock request to PowerManager.
  EXPECT_TRUE(tester->IsLocked());

  // Emulate LockScreen request from PowerManager (via SessionManager).
  // TODO(oshima): Find out better way to handle this in mock.
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) {
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  {
    Waiter waiter(browser());
    browser()->ToggleFullscreenMode();
    waiter.Wait(false /* not locked */, true /* full screen */);
    EXPECT_TRUE(browser()->window()->IsFullscreen());
    EXPECT_FALSE(tester->IsLocked());
  }
  {
    Waiter waiter(browser());
    UserManager::Get()->UserLoggedIn("user");
    ScreenLocker::Show();
    tester->EmulateWindowManagerReady();
    waiter.Wait(true /* locked */, false /* full screen */);
    EXPECT_FALSE(browser()->window()->IsFullscreen());
    EXPECT_TRUE(tester->IsLocked());
  }
  tester->InjectMockAuthenticator("user", "pass");
  tester->EnterPassword("pass");
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

void MouseMove(views::Widget* widget) {
  ui_controls::SendMouseMove(10, 10);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseMove) {
  TestNoPassword(MouseMove);
}

void MouseClick(views::Widget* widget) {
  ui_controls::SendMouseClick(ui_controls::RIGHT);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseClick) {
  TestNoPassword(MouseClick);
}

void KeyPress(views::Widget* widget) {
  ui_controls::SendKeyPress(GTK_WINDOW(widget->GetNativeView()),
                            base::VKEY_SPACE, false, false, false, false);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithKeyPress) {
  TestNoPassword(KeyPress);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestShowTwice) {
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
      .Times(2)
      .RetiresOnSaturation();

  UserManager::Get()->UserLoggedIn("user");
  ScreenLocker::Show();
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  tester->EmulateWindowManagerReady();
  ui_test_utils::WaitForNotification(
      NotificationType::SCREEN_LOCK_STATE_CHANGED);
  EXPECT_TRUE(tester->IsLocked());

  // Calling Show again simply send LockCompleted signal.
  ScreenLocker::Show();
  EXPECT_TRUE(tester->IsLocked());

  // Close the locker to match expectations.
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

}  // namespace chromeos
<commit_msg>add expectations that were removed from setup in other cl.<commit_after>// Copyright (c) 2010 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 "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/automation/ui_controls.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_screen_lock_library.h"
#include "chrome/browser/chromeos/cros/mock_input_method_library.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/login/screen_locker_tester.h"
#include "chrome/browser/chromeos/login/mock_authenticator.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/views/browser_dialogs.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "views/controls/textfield/textfield.h"
#include "views/window/window_gtk.h"

namespace {

// An object that wait for lock state and fullscreen state.
class Waiter : public NotificationObserver {
 public:
  Waiter(Browser* browser)
      : browser_(browser) {
    registrar_.Add(this,
                   NotificationType::SCREEN_LOCK_STATE_CHANGED,
                   NotificationService::AllSources());
    handler_id_ = g_signal_connect(
        G_OBJECT(browser_->window()->GetNativeHandle()),
        "window-state-event",
        G_CALLBACK(OnWindowStateEventThunk),
        this);
  }

  ~Waiter() {
    g_signal_handler_disconnect(
        G_OBJECT(browser_->window()->GetNativeHandle()),
        handler_id_);
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    DCHECK(type == NotificationType::SCREEN_LOCK_STATE_CHANGED);
    MessageLoop::current()->Quit();
  }

  // Wait until the two conditions are met.
  void Wait(bool locker_state, bool fullscreen) {
    scoped_ptr<chromeos::test::ScreenLockerTester>
        tester(chromeos::ScreenLocker::GetTester());
    while (tester->IsLocked() != locker_state ||
           browser_->window()->IsFullscreen() != fullscreen) {
      ui_test_utils::RunMessageLoop();
    }
    // Make sure all pending tasks are executed.
    ui_test_utils::RunAllPendingInMessageLoop();
  }

  CHROMEGTK_CALLBACK_1(Waiter, gboolean, OnWindowStateEvent,
                       GdkEventWindowState*);

 private:
  Browser* browser_;
  gulong handler_id_;
  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(Waiter);
};

gboolean Waiter::OnWindowStateEvent(GtkWidget* widget,
                                    GdkEventWindowState* event) {
  MessageLoop::current()->Quit();
  return false;
}

}  // namespace

namespace chromeos {

class ScreenLockerTest : public CrosInProcessBrowserTest {
 public:
  ScreenLockerTest() {}

 protected:

  // Test the no password mode with different unlock scheme given by
  // |unlock| function.
  void TestNoPassword(void (unlock)(views::Widget*)) {
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested())
        .Times(1)
        .RetiresOnSaturation();
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
        .Times(1)
        .RetiresOnSaturation();
    UserManager::Get()->OffTheRecordUserLoggedIn();
    ScreenLocker::Show();
    scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
    tester->EmulateWindowManagerReady();
    ui_test_utils::WaitForNotification(
        NotificationType::SCREEN_LOCK_STATE_CHANGED);
    EXPECT_TRUE(tester->IsLocked());
    tester->InjectMockAuthenticator("", "");

    unlock(tester->GetWidget());

    ui_test_utils::RunAllPendingInMessageLoop();
    EXPECT_TRUE(tester->IsLocked());

    // Emulate LockScreen request from PowerManager (via SessionManager).
    ScreenLocker::Hide();
    ui_test_utils::RunAllPendingInMessageLoop();
    EXPECT_FALSE(tester->IsLocked());
  }

 private:
  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    InitMockScreenLockLibrary();
    EXPECT_CALL(*mock_screen_lock_library_, AddObserver(testing::_))
        .Times(1)
        .RetiresOnSaturation();
    EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockCompleted())
        .Times(1)
        .RetiresOnSaturation();
    // Expectations for the status are on the screen lock window.
    SetStatusAreaMocksExpectations();
    // Expectations for the status area on the browser window.
    SetStatusAreaMocksExpectations();
  }

  virtual void SetUpCommandLine(CommandLine* command_line) {
    command_line->AppendSwitchWithValue(switches::kLoginProfile, "user");
    command_line->AppendSwitch(switches::kNoFirstRun);
  }

  DISALLOW_COPY_AND_ASSIGN(ScreenLockerTest);
};

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestBasic) {
  EXPECT_CALL(*mock_input_method_library_, GetNumActiveInputMethods())
      .Times(1)
      .WillRepeatedly((testing::Return(0)))
      .RetiresOnSaturation();
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested())
      .Times(1)
      .RetiresOnSaturation();
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
      .Times(1)
      .RetiresOnSaturation();
  UserManager::Get()->UserLoggedIn("user");
  ScreenLocker::Show();
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  tester->EmulateWindowManagerReady();
  ui_test_utils::WaitForNotification(
      NotificationType::SCREEN_LOCK_STATE_CHANGED);

  tester->InjectMockAuthenticator("user", "pass");
  EXPECT_TRUE(tester->IsLocked());
  tester->EnterPassword("fail");
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_TRUE(tester->IsLocked());
  tester->EnterPassword("pass");
  ui_test_utils::RunAllPendingInMessageLoop();
  // Successful authentication simply send a unlock request to PowerManager.
  EXPECT_TRUE(tester->IsLocked());

  // Emulate LockScreen request from PowerManager (via SessionManager).
  // TODO(oshima): Find out better way to handle this in mock.
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestFullscreenExit) {
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenUnlockRequested())
      .Times(1)
      .RetiresOnSaturation();
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
      .Times(1)
      .RetiresOnSaturation();
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  {
    Waiter waiter(browser());
    browser()->ToggleFullscreenMode();
    waiter.Wait(false /* not locked */, true /* full screen */);
    EXPECT_TRUE(browser()->window()->IsFullscreen());
    EXPECT_FALSE(tester->IsLocked());
  }
  {
    Waiter waiter(browser());
    UserManager::Get()->UserLoggedIn("user");
    ScreenLocker::Show();
    tester->EmulateWindowManagerReady();
    waiter.Wait(true /* locked */, false /* full screen */);
    EXPECT_FALSE(browser()->window()->IsFullscreen());
    EXPECT_TRUE(tester->IsLocked());
  }
  tester->InjectMockAuthenticator("user", "pass");
  tester->EnterPassword("pass");
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

void MouseMove(views::Widget* widget) {
  ui_controls::SendMouseMove(10, 10);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseMove) {
  TestNoPassword(MouseMove);
}

void MouseClick(views::Widget* widget) {
  ui_controls::SendMouseClick(ui_controls::RIGHT);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithMouseClick) {
  TestNoPassword(MouseClick);
}

void KeyPress(views::Widget* widget) {
  ui_controls::SendKeyPress(GTK_WINDOW(widget->GetNativeView()),
                            base::VKEY_SPACE, false, false, false, false);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestNoPasswordWithKeyPress) {
  TestNoPassword(KeyPress);
}

IN_PROC_BROWSER_TEST_F(ScreenLockerTest, TestShowTwice) {
  EXPECT_CALL(*mock_screen_lock_library_, NotifyScreenLockCompleted())
      .Times(2)
      .RetiresOnSaturation();

  UserManager::Get()->UserLoggedIn("user");
  ScreenLocker::Show();
  scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester());
  tester->EmulateWindowManagerReady();
  ui_test_utils::WaitForNotification(
      NotificationType::SCREEN_LOCK_STATE_CHANGED);
  EXPECT_TRUE(tester->IsLocked());

  // Calling Show again simply send LockCompleted signal.
  ScreenLocker::Show();
  EXPECT_TRUE(tester->IsLocked());

  // Close the locker to match expectations.
  ScreenLocker::Hide();
  ui_test_utils::RunAllPendingInMessageLoop();
  EXPECT_FALSE(tester->IsLocked());
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/in_process_webkit/indexed_db_context.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        browser(), test_url, 2);
    std::string result = browser()->GetSelectedTabContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          browser()->GetSelectedTabContents()->render_view_host(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
  // Create test files.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath indexeddb_dir = temp_dir.path().Append(
      IndexedDBContext::kIndexedDBDirectory);
  ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir));

  FilePath::StringType file_name_1(FILE_PATH_LITERAL("http_www.google.com_0"));
  file_name_1.append(IndexedDBContext::kIndexedDBExtension);
  FilePath::StringType file_name_2(FILE_PATH_LITERAL("https_www.google.com_0"));
  file_name_2.append(IndexedDBContext::kIndexedDBExtension);
  FilePath temp_file_path_1 = indexeddb_dir.Append(file_name_1);
  FilePath temp_file_path_2 = indexeddb_dir.Append(file_name_2);

  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_1, ".", 1));
  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_2, "o", 1));

  IndexedDBContext::ClearLocalState(temp_dir.path(), "https");

  // Because we specified https for scheme to be skipped the second file
  // should survive and the first go into vanity.
  ASSERT_FALSE(file_util::PathExists(temp_file_path_1));
  ASSERT_TRUE(file_util::PathExists(temp_file_path_2));
}
<commit_msg>Mark 2 IndexedDBBrowserTests as flaky. BUG=63675 TEST=none TBR=jochen@chromium.org Review URL: http://codereview.chromium.org/5182007<commit_after>// Copyright (c) 2010 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 "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/ref_counted.h"
#include "base/scoped_temp_dir.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/in_process_webkit/indexed_db_context.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"

// This browser test is aimed towards exercising the IndexedDB bindings and
// the actual implementation that lives in the browser side (in_process_webkit).
class IndexedDBBrowserTest : public InProcessBrowserTest {
 public:
  IndexedDBBrowserTest() {
    EnableDOMAutomation();
  }

  GURL testUrl(const FilePath& file_path) {
    const FilePath kTestDir(FILE_PATH_LITERAL("indexeddb"));
    return ui_test_utils::GetTestUrl(kTestDir, file_path);
  }

  void SimpleTest(const GURL& test_url) {
    // The test page will perform tests on IndexedDB, then navigate to either
    // a #pass or #fail ref.
    ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
        browser(), test_url, 2);
    std::string result = browser()->GetSelectedTabContents()->GetURL().ref();
    if (result != "pass") {
      std::string js_result;
      ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString(
          browser()->GetSelectedTabContents()->render_view_host(), L"",
          L"window.domAutomationController.send(getLog())", &js_result));
      FAIL() << "Failed: " << js_result;
    }
  }
};

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, IndexTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html"))));
}

// See http://crbug.com/63675.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_KeyPathTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("key_path_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, TransactionGetTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_get_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ObjectStoreTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("object_store_test.html"))));
}

IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DatabaseTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("database_test.html"))));
}

// See http://crbug.com/63675.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, FLAKY_TransactionTest) {
  SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("transaction_test.html"))));
}

// In proc browser test is needed here because ClearLocalState indirectly calls
// WebKit's isMainThread through WebSecurityOrigin->SecurityOrigin.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ClearLocalState) {
  // Create test files.
  ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  FilePath indexeddb_dir = temp_dir.path().Append(
      IndexedDBContext::kIndexedDBDirectory);
  ASSERT_TRUE(file_util::CreateDirectory(indexeddb_dir));

  FilePath::StringType file_name_1(FILE_PATH_LITERAL("http_www.google.com_0"));
  file_name_1.append(IndexedDBContext::kIndexedDBExtension);
  FilePath::StringType file_name_2(FILE_PATH_LITERAL("https_www.google.com_0"));
  file_name_2.append(IndexedDBContext::kIndexedDBExtension);
  FilePath temp_file_path_1 = indexeddb_dir.Append(file_name_1);
  FilePath temp_file_path_2 = indexeddb_dir.Append(file_name_2);

  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_1, ".", 1));
  ASSERT_EQ(1, file_util::WriteFile(temp_file_path_2, "o", 1));

  IndexedDBContext::ClearLocalState(temp_dir.path(), "https");

  // Because we specified https for scheme to be skipped the second file
  // should survive and the first go into vanity.
  ASSERT_FALSE(file_util::PathExists(temp_file_path_1));
  ASSERT_TRUE(file_util::PathExists(temp_file_path_2));
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2019 Anton Kozhevnikov, Thomas Schulthess
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
//    following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
//    and the following disclaimer in the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/** \file fft.hpp
 *
 *  \brief Contains helper functions for the interface with SpFFT library.
 */

#ifndef __FFT_HPP__
#define __FFT_HPP__

#include "splindex.hpp"
#include "communicator.hpp"
#include "spfft/spfft.hpp"

using double_complex = std::complex<double>;

const std::map<SpfftProcessingUnitType, sddk::memory_t> spfft_memory_t = {
    {SPFFT_PU_HOST, sddk::memory_t::host},
    {SPFFT_PU_GPU, sddk::memory_t::device}
};

template <typename F, typename T, typename ...Args>
using enable_return = typename std::enable_if<std::is_same<typename std::result_of<F(Args...)>::type, T>::value, void>::type;

/// Load data from real-valued lambda.
template <typename F>
inline enable_return<F, double, int>
spfft_input(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = double_complex(fr__(i), 0.0);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = fr__(i);
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

/// Loda data from complex-valued lambda.
template <typename F>
inline enable_return<F, std::complex<double>, int>
spfft_input(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = fr__(i);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

template <typename T>
inline void spfft_input(spfft::Transform& spfft__, T const* data__)
{
    spfft_input(spfft__, [&](int ir){return data__[ir];});
}

template <typename F>
inline void spfft_multiply(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] *= fr__(i);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] *= fr__(i);
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline void spfft_output(spfft::Transform& spfft__, double* data__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = std::real(ptr[i]);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = ptr[i];
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline void spfft_output(spfft::Transform& spfft__, double_complex* data__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = ptr[i];
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            /* can't be a R2C transform and complex output data */
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline size_t spfft_grid_size(spfft::Transform const& spfft__)
{
    return spfft__.dim_x() * spfft__.dim_y() * spfft__.dim_z();
}

inline sddk::splindex<sddk::splindex_t::block> split_fft_z(int size_z__, sddk::Communicator const& comm_fft__)
{
    return sddk::splindex<sddk::splindex_t::block>(size_z__, comm_fft__.size(), comm_fft__.rank());
}

#endif // __FFT3D_H__

/** \page ft_pw Fourier transform and plane wave normalization
 *
 *  FFT convention:
 *  \f[
 *      f({\bf r}) = \sum_{{\bf G}} e^{i{\bf G}{\bf r}} f({\bf G})
 *  \f]
 *  is a \em backward transformation from a set of pw coefficients to a function.
 *
 *  \f[
 *      f({\bf G}) = \frac{1}{\Omega} \int e^{-i{\bf G}{\bf r}} f({\bf r}) d {\bf r} =
 *          \frac{1}{N} \sum_{{\bf r}_j} e^{-i{\bf G}{\bf r}_j} f({\bf r}_j)
 *  \f]
 *  is a \em forward transformation from a function to a set of coefficients.

 *  We use plane waves in two different cases: a) plane waves (or augmented plane waves in the case of APW+lo method)
 *  as a basis for expanding Kohn-Sham wave functions and b) plane waves are used to expand charge density and
 *  potential. When we are dealing with plane wave basis functions it is convenient to adopt the following
 *  normalization:
 *  \f[
 *      \langle {\bf r} |{\bf G+k} \rangle = \frac{1}{\sqrt \Omega} e^{i{\bf (G+k)r}}
 *  \f]
 *  such that
 *  \f[
 *      \langle {\bf G+k} |{\bf G'+k} \rangle_{\Omega} = \delta_{{\bf GG'}}
 *  \f]
 *  in the unit cell. However, for the expansion of periodic functions such as density or potential, the following
 *  convention is more appropriate:
 *  \f[
 *      \rho({\bf r}) = \sum_{\bf G} e^{i{\bf Gr}} \rho({\bf G})
 *  \f]
 *  where
 *  \f[
 *      \rho({\bf G}) = \frac{1}{\Omega} \int_{\Omega} e^{-i{\bf Gr}} \rho({\bf r}) d{\bf r} =
 *          \frac{1}{\Omega} \sum_{{\bf r}_i} e^{-i{\bf Gr}_i} \rho({\bf r}_i) \frac{\Omega}{N} =
 *          \frac{1}{N} \sum_{{\bf r}_i} e^{-i{\bf Gr}_i} \rho({\bf r}_i)
 *  \f]
 *  i.e. with such convention the plane-wave expansion coefficients are obtained with a normalized FFT.
 */
<commit_msg>fix typo<commit_after>// Copyright (c) 2013-2019 Anton Kozhevnikov, Thomas Schulthess
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
//    following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
//    and the following disclaimer in the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/** \file fft.hpp
 *
 *  \brief Contains helper functions for the interface with SpFFT library.
 */

#ifndef __FFT_HPP__
#define __FFT_HPP__

#include "splindex.hpp"
#include "communicator.hpp"
#include "spfft/spfft.hpp"

using double_complex = std::complex<double>;

const std::map<SpfftProcessingUnitType, sddk::memory_t> spfft_memory_t = {
    {SPFFT_PU_HOST, sddk::memory_t::host},
    {SPFFT_PU_GPU, sddk::memory_t::device}
};

template <typename F, typename T, typename ...Args>
using enable_return = typename std::enable_if<std::is_same<typename std::result_of<F(Args...)>::type, T>::value, void>::type;

/// Load data from real-valued lambda.
template <typename F>
inline enable_return<F, double, int>
spfft_input(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = double_complex(fr__(i), 0.0);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = fr__(i);
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

/// Load data from complex-valued lambda.
template <typename F>
inline enable_return<F, std::complex<double>, int>
spfft_input(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] = fr__(i);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

template <typename T>
inline void spfft_input(spfft::Transform& spfft__, T const* data__)
{
    spfft_input(spfft__, [&](int ir){return data__[ir];});
}

template <typename F>
inline void spfft_multiply(spfft::Transform& spfft__, F&& fr__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] *= fr__(i);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                ptr[i] *= fr__(i);
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline void spfft_output(spfft::Transform& spfft__, double* data__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = std::real(ptr[i]);
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            auto ptr = reinterpret_cast<double*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = ptr[i];
            }
            break;
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline void spfft_output(spfft::Transform& spfft__, double_complex* data__)
{
    switch (spfft__.type()) {
        case SPFFT_TRANS_C2C: {
            auto ptr = reinterpret_cast<double_complex*>(spfft__.space_domain_data(SPFFT_PU_HOST));
            #pragma omp parallel for schedule(static)
            for (int i = 0; i < spfft__.local_slice_size(); i++) {
                data__[i] = ptr[i];
            }
            break;
        }
        case SPFFT_TRANS_R2C: {
            /* can't be a R2C transform and complex output data */
        }
        default: {
            throw std::runtime_error("wrong spfft type");
        }
    }
}

inline size_t spfft_grid_size(spfft::Transform const& spfft__)
{
    return spfft__.dim_x() * spfft__.dim_y() * spfft__.dim_z();
}

inline sddk::splindex<sddk::splindex_t::block> split_fft_z(int size_z__, sddk::Communicator const& comm_fft__)
{
    return sddk::splindex<sddk::splindex_t::block>(size_z__, comm_fft__.size(), comm_fft__.rank());
}

#endif // __FFT3D_H__

/** \page ft_pw Fourier transform and plane wave normalization
 *
 *  FFT convention:
 *  \f[
 *      f({\bf r}) = \sum_{{\bf G}} e^{i{\bf G}{\bf r}} f({\bf G})
 *  \f]
 *  is a \em backward transformation from a set of pw coefficients to a function.
 *
 *  \f[
 *      f({\bf G}) = \frac{1}{\Omega} \int e^{-i{\bf G}{\bf r}} f({\bf r}) d {\bf r} =
 *          \frac{1}{N} \sum_{{\bf r}_j} e^{-i{\bf G}{\bf r}_j} f({\bf r}_j)
 *  \f]
 *  is a \em forward transformation from a function to a set of coefficients.

 *  We use plane waves in two different cases: a) plane waves (or augmented plane waves in the case of APW+lo method)
 *  as a basis for expanding Kohn-Sham wave functions and b) plane waves are used to expand charge density and
 *  potential. When we are dealing with plane wave basis functions it is convenient to adopt the following
 *  normalization:
 *  \f[
 *      \langle {\bf r} |{\bf G+k} \rangle = \frac{1}{\sqrt \Omega} e^{i{\bf (G+k)r}}
 *  \f]
 *  such that
 *  \f[
 *      \langle {\bf G+k} |{\bf G'+k} \rangle_{\Omega} = \delta_{{\bf GG'}}
 *  \f]
 *  in the unit cell. However, for the expansion of periodic functions such as density or potential, the following
 *  convention is more appropriate:
 *  \f[
 *      \rho({\bf r}) = \sum_{\bf G} e^{i{\bf Gr}} \rho({\bf G})
 *  \f]
 *  where
 *  \f[
 *      \rho({\bf G}) = \frac{1}{\Omega} \int_{\Omega} e^{-i{\bf Gr}} \rho({\bf r}) d{\bf r} =
 *          \frac{1}{\Omega} \sum_{{\bf r}_i} e^{-i{\bf Gr}_i} \rho({\bf r}_i) \frac{\Omega}{N} =
 *          \frac{1}{N} \sum_{{\bf r}_i} e^{-i{\bf Gr}_i} \rho({\bf r}_i)
 *  \f]
 *  i.e. with such convention the plane-wave expansion coefficients are obtained with a normalized FFT.
 */
<|endoftext|>