File: node_channel_unittest.cc

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (133 lines) | stat: -rw-r--r-- 4,544 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
#pragma allow_unsafe_libc_calls
#endif

#include "mojo/core/node_channel.h"

#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/test/mock_node_channel_delegate.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace mojo {
namespace core {
namespace {

using ports::NodeName;
using testing::_;

class NodeChannelTest : public testing::Test {
 public:
  void SetUp() override {
    if (IsMojoIpczEnabled()) {
      GTEST_SKIP() << "NodeChannel is never used when ipcz is enabled, so "
                   << "these tests are neither supported nor relevant.";
    }
  }

  MockNodeChannelDelegate local_delegate_;
  MockNodeChannelDelegate remote_delegate_;
};

scoped_refptr<NodeChannel> CreateNodeChannel(NodeChannel::Delegate* delegate,
                                             PlatformChannelEndpoint endpoint) {
  return NodeChannel::Create(delegate, ConnectionParams(std::move(endpoint)),
                             Channel::HandlePolicy::kAcceptHandles,
                             GetIOTaskRunner(), base::NullCallback());
}

TEST_F(NodeChannelTest, DestructionIsSafe) {
  // Regression test for https://crbug.com/1081874.
  base::test::TaskEnvironment task_environment;

  PlatformChannel channel;
  auto local_channel =
      CreateNodeChannel(&local_delegate_, channel.TakeLocalEndpoint());
  local_channel->Start();
  auto remote_channel =
      CreateNodeChannel(&remote_delegate_, channel.TakeRemoteEndpoint());
  remote_channel->Start();

  // Verify end-to-end operation
  const NodeName kRemoteNodeName{123, 456};
  const NodeName kToken{987, 654};
  base::RunLoop loop;
  EXPECT_CALL(local_delegate_,
              OnAcceptInvitee(ports::kInvalidNodeName, kRemoteNodeName, kToken))
      .WillRepeatedly([&] { loop.Quit(); });
  remote_channel->AcceptInvitee(kRemoteNodeName, kToken);
  loop.Run();

  // Now send another message to the local endpoint but tear it down
  // immediately. This will race with the message being received on the IO
  // thread, and although the corresponding delegate call may or may not
  // dispatch as a result, the race should still be memory-safe.
  remote_channel->AcceptInvitee(kRemoteNodeName, kToken);

  base::RunLoop error_loop;
  EXPECT_CALL(remote_delegate_, OnChannelError).WillOnce([&] {
    error_loop.Quit();
  });
  local_channel.reset();
  error_loop.Run();
}

TEST_F(NodeChannelTest, MessagesCannotBeSmallerThanOldestVersion) {
  base::test::TaskEnvironment task_environment;

  PlatformChannel channel;
  auto local_channel =
      CreateNodeChannel(&local_delegate_, channel.TakeLocalEndpoint());
  local_channel->Start();
  auto remote_channel =
      CreateNodeChannel(&remote_delegate_, channel.TakeRemoteEndpoint());
  remote_channel->Start();

  base::RunLoop loop;

  // It's a bad message and shouldn't be passed to the delegate.
  EXPECT_CALL(local_delegate_, OnRequestPortMerge(_, _, _)).Times(0);

  // This good message should go through after.
  const NodeName kRemoteNodeName{123, 456};
  const NodeName kToken{987, 654};
  EXPECT_CALL(local_delegate_,
              OnAcceptInvitee(ports::kInvalidNodeName, kRemoteNodeName, kToken))
      .WillRepeatedly([&] { loop.Quit(); });

  // 1 byte is not enough to contain the oldest version of the request port
  // merge payload, it should be discarded.
  int payload_size = 1;
  int capacity = /*sizeof(header)=*/8 + payload_size;
  auto message =
      Channel::Message::CreateMessage(capacity, capacity, /*num_handles=*/0);

  memset(message->mutable_payload(), 0, capacity);

  // Set the type of this message as REQUEST_PORT_MERGE (6)
  *reinterpret_cast<uint32_t*>(message->mutable_payload()) = 6;

  // This short message should be ignored.
  remote_channel->SendChannelMessage(std::move(message));
  remote_channel->AcceptInvitee(kRemoteNodeName, kToken);
  loop.Run();

  remote_channel->ShutDown();
  local_channel->ShutDown();
}

}  // namespace
}  // namespace core
}  // namespace mojo