普通文本  |  167行  |  5.51 KB

// Copyright 2017 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/macros.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_task_environment.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
#include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace {

class LazySerializationTest : public testing::Test {
 public:
  LazySerializationTest() {}
  ~LazySerializationTest() override {}

 private:
  base::test::ScopedTaskEnvironment task_environment_;

  DISALLOW_COPY_AND_ASSIGN(LazySerializationTest);
};

class TestUnserializedStructImpl : public test::TestUnserializedStruct {
 public:
  explicit TestUnserializedStructImpl(
      test::TestUnserializedStructRequest request)
      : binding_(this, std::move(request)) {}
  ~TestUnserializedStructImpl() override {}

  // test::TestUnserializedStruct:
  void PassUnserializedStruct(
      const test::StructWithUnreachableTraitsImpl& s,
      const PassUnserializedStructCallback& callback) override {
    callback.Run(s);
  }

 private:
  mojo::Binding<test::TestUnserializedStruct> binding_;

  DISALLOW_COPY_AND_ASSIGN(TestUnserializedStructImpl);
};

class ForceSerializeTesterImpl : public test::ForceSerializeTester {
 public:
  ForceSerializeTesterImpl(test::ForceSerializeTesterRequest request)
      : binding_(this, std::move(request)) {}
  ~ForceSerializeTesterImpl() override = default;

  // test::ForceSerializeTester:
  void SendForceSerializedStruct(
      const test::StructForceSerializeImpl& s,
      const SendForceSerializedStructCallback& callback) override {
    callback.Run(s);
  }

  void SendNestedForceSerializedStruct(
      const test::StructNestedForceSerializeImpl& s,
      const SendNestedForceSerializedStructCallback& callback) override {
    callback.Run(s);
  }

 private:
  Binding<test::ForceSerializeTester> binding_;

  DISALLOW_COPY_AND_ASSIGN(ForceSerializeTesterImpl);
};

TEST_F(LazySerializationTest, NeverSerialize) {
  // Basic sanity check to ensure that no messages are serialized by default in
  // environments where lazy serialization is supported, on an interface which
  // supports lazy serialization, and where both ends of the interface are in
  // the same process.

  test::TestUnserializedStructPtr ptr;
  TestUnserializedStructImpl impl(MakeRequest(&ptr));

  const int32_t kTestMagicNumber = 42;

  test::StructWithUnreachableTraitsImpl data;
  EXPECT_EQ(0, data.magic_number);
  data.magic_number = kTestMagicNumber;

  // Send our data over the pipe and wait for it to come back. The value should
  // be preserved. We know the data was never serialized because the
  // StructTraits for this type will DCHECK if executed in any capacity.
  int received_number = 0;
  base::RunLoop loop;
  ptr->PassUnserializedStruct(
      data, base::Bind(
                [](base::RunLoop* loop, int* received_number,
                   const test::StructWithUnreachableTraitsImpl& passed) {
                  *received_number = passed.magic_number;
                  loop->Quit();
                },
                &loop, &received_number));
  loop.Run();
  EXPECT_EQ(kTestMagicNumber, received_number);
}

TEST_F(LazySerializationTest, ForceSerialize) {
  // Verifies that the [force_serialize] attribute works as intended: i.e., even
  // with lazy serialization enabled, messages which carry a force-serialized
  // type will always serialize at call time.

  test::ForceSerializeTesterPtr tester;
  ForceSerializeTesterImpl impl(mojo::MakeRequest(&tester));

  constexpr int32_t kTestValue = 42;

  base::RunLoop loop;
  test::StructForceSerializeImpl in;
  in.set_value(kTestValue);
  EXPECT_FALSE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
  tester->SendForceSerializedStruct(
      in, base::BindLambdaForTesting(
              [&](const test::StructForceSerializeImpl& passed) {
                EXPECT_EQ(kTestValue, passed.value());
                EXPECT_TRUE(passed.was_deserialized());
                EXPECT_FALSE(passed.was_serialized());
                loop.Quit();
              }));
  EXPECT_TRUE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
  loop.Run();
  EXPECT_TRUE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
}

TEST_F(LazySerializationTest, ForceSerializeNested) {
  // Verifies that the [force_serialize] attribute works as intended in a nested
  // context, i.e. when a force-serialized type is contained within a
  // non-force-serialized type,

  test::ForceSerializeTesterPtr tester;
  ForceSerializeTesterImpl impl(mojo::MakeRequest(&tester));

  constexpr int32_t kTestValue = 42;

  base::RunLoop loop;
  test::StructNestedForceSerializeImpl in;
  in.force().set_value(kTestValue);
  EXPECT_FALSE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
  tester->SendNestedForceSerializedStruct(
      in, base::BindLambdaForTesting(
              [&](const test::StructNestedForceSerializeImpl& passed) {
                EXPECT_EQ(kTestValue, passed.force().value());
                EXPECT_TRUE(passed.was_deserialized());
                EXPECT_FALSE(passed.was_serialized());
                loop.Quit();
              }));
  EXPECT_TRUE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
  loop.Run();
  EXPECT_TRUE(in.was_serialized());
  EXPECT_FALSE(in.was_deserialized());
}

}  // namespace
}  // namespace mojo