165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes/*
265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Copyright (C) 2014 The Android Open Source Project
365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes *
465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * you may not use this file except in compliance with the License.
665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * You may obtain a copy of the License at
765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes *
865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes *
1065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * See the License for the specific language governing permissions and
1465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes * limitations under the License.
1565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes */
1665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
17f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <pty.h>
18f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
1965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes#include <gtest/gtest.h>
2065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
21f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <pthread.h>
2265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes#include <sys/ioctl.h>
2365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
24f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <atomic>
25f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
26f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui#include <android-base/file.h>
27f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
2833697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes#include "utils.h"
2933697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes
3065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott HughesTEST(pty, openpty) {
3165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  int master, slave;
3265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  char name[32];
3365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  struct winsize w = { 123, 456, 9999, 999 };
3465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(0, openpty(&master, &slave, name, NULL, &w));
3565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_NE(-1, master);
3665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_NE(-1, slave);
3765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_NE(master, slave);
3865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
3965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  char tty_name[32];
4065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(0, ttyname_r(slave, tty_name, sizeof(tty_name)));
4165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_STREQ(tty_name, name);
4265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
4365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  struct winsize w_actual;
4465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(0, ioctl(slave, TIOCGWINSZ, &w_actual));
4565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(w_actual.ws_row, w.ws_row);
4665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(w_actual.ws_col, w.ws_col);
4765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(w_actual.ws_xpixel, w.ws_xpixel);
4865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(w_actual.ws_ypixel, w.ws_ypixel);
4965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
5065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  close(master);
5165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  close(slave);
5265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes}
5365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
5465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott HughesTEST(pty, forkpty) {
5565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  pid_t sid = getsid(0);
5665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
5765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  int master;
5865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  pid_t pid = forkpty(&master, NULL, NULL, NULL);
5965f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_NE(-1, pid);
6065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
6165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  if (pid == 0) {
6265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes    // We're the child.
6365f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes    ASSERT_NE(sid, getsid(0));
6465f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes    _exit(0);
6565f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  }
6665f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
6765f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  ASSERT_EQ(sid, getsid(0));
6865f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
6933697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes  AssertChildExited(pid, 0);
7065f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes
7165f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes  close(master);
7265f0df78730fb0d6994f9d4d0a16dc0241081d94Elliott Hughes}
73f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
74f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cuistruct PtyReader_28979140_Arg {
75c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  int main_cpu_id;
76c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  int slave_fd;
77c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  uint32_t data_count;
78c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  bool finished;
79c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  std::atomic<bool> matched;
80f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui};
81f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
82f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cuistatic void PtyReader_28979140(PtyReader_28979140_Arg* arg) {
83f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  arg->finished = false;
84f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  cpu_set_t cpus;
85f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus));
86c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  CPU_CLR(arg->main_cpu_id, &cpus);
87f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
88f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
89f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  uint32_t counter = 0;
90f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  while (counter <= arg->data_count) {
91f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    char buf[4096];  // Use big buffer to read to hit the bug more easily.
92f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    size_t to_read = std::min(sizeof(buf), (arg->data_count + 1 - counter) * sizeof(uint32_t));
93f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    ASSERT_TRUE(android::base::ReadFully(arg->slave_fd, buf, to_read));
94f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    size_t num_of_value = to_read / sizeof(uint32_t);
95f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    uint32_t* p = reinterpret_cast<uint32_t*>(buf);
96f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    while (num_of_value-- > 0) {
97f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui      if (*p++ != counter++) {
98f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui        arg->matched = false;
99f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui      }
100f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    }
101f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  }
102f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  close(arg->slave_fd);
103f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  arg->finished = true;
104f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui}
105f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
106f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin CuiTEST(pty, bug_28979140) {
107f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  // This test is to test a kernel bug, which uses a lock free ring-buffer to
108f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  // pass data through a raw pty, but missing necessary memory barriers.
109c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  cpu_set_t cpus;
110c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus));
111c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  if (CPU_COUNT(&cpus) < 2) {
112f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    GTEST_LOG_(INFO) << "This test tests bug happens only on multiprocessors.";
113f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    return;
114f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  }
115f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  constexpr uint32_t TEST_DATA_COUNT = 200000;
116f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
117f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  // 1. Open raw pty.
118f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  int master;
119f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  int slave;
120f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr));
121f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  termios tattr;
122f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, tcgetattr(slave, &tattr));
123f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  cfmakeraw(&tattr);
124f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr));
125f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
126c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  // 2. Make master thread and slave thread running on different cpus:
127c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  // master thread uses first available cpu, and slave thread uses other cpus.
128f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  PtyReader_28979140_Arg arg;
129c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  arg.main_cpu_id = -1;
130c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  for (int i = 0; i < CPU_SETSIZE; i++) {
131c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko    if (CPU_ISSET(i, &cpus)) {
132c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko      arg.main_cpu_id = i;
133c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko      break;
134c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko    }
135c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  }
136c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  ASSERT_GE(arg.main_cpu_id, 0);
137c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko
138c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  // 3. Create thread for slave reader.
139c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  pthread_t thread;
140f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  arg.slave_fd = slave;
141f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  arg.data_count = TEST_DATA_COUNT;
142f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  arg.matched = true;
143f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, pthread_create(&thread, nullptr,
144f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui                              reinterpret_cast<void*(*)(void*)>(PtyReader_28979140),
145f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui                              &arg));
146f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
147f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  CPU_ZERO(&cpus);
148c14d7f0a30c7a72d0f0906a75f268003e64c2df6Alex Vakulenko  CPU_SET(arg.main_cpu_id, &cpus);
149f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
150f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui
151f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  // 4. Send data to slave.
152f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  uint32_t counter = 0;
153f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  while (counter <= TEST_DATA_COUNT) {
154f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    ASSERT_TRUE(android::base::WriteFully(master, &counter, sizeof(counter)));
155f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    ASSERT_TRUE(arg.matched) << "failed at count = " << counter;
156f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui    counter++;
157f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  }
158f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_EQ(0, pthread_join(thread, nullptr));
159f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_TRUE(arg.finished);
160f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  ASSERT_TRUE(arg.matched);
161f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui  close(master);
162f35c6bc70fcf9907c28eb169a294a42dcae52f93Yabin Cui}
163