15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <errno.h> 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <fcntl.h> 73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <string.h> 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <sys/ioctl.h> 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <sys/select.h> 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <sys/stat.h> 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <sys/time.h> 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <string> 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "dev_fs_for_testing.h" 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "gtest/gtest.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/devfs/dev_fs.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/filesystem.h" 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/ioctl.h" 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/kernel_intercept.h" 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/kernel_proxy.h" 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/osdirent.h" 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using namespace nacl_io; 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace { 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static int ki_ioctl_wrapper(int fd, int request, ...) { 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_list ap; 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_start(ap, request); 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int rtn = ki_ioctl(fd, request, ap); 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_end(ap); 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return rtn; 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class TtyNodeTest : public ::testing::Test { 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public: 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TtyNodeTest() : fs_(&ppapi_) {} 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void SetUp() { 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(0, fs_.Open(Path("/tty"), O_RDWR, &dev_tty_)); 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_NE(NULL_NODE, dev_tty_.get()); 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci struct stat buf; 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ(0, dev_tty_->GetStat(&buf)); 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_EQ(S_IRUSR | S_IWUSR, buf.st_mode & S_IRWXU); 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) protected: 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FakePepperInterface ppapi_; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DevFsForTesting fs_; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedNode dev_tty_; 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class TtyTest : public ::testing::Test { 54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) public: 55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void SetUp() { 56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_EQ(0, ki_push_state_for_testing()); 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ASSERT_EQ(0, ki_init_interface(&kp_, &ppapi_)); 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var_iface_ = ppapi_.GetVarInterface(); 60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) void TearDown() { 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ki_uninit(); 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int TtyWrite(int fd, const char* string) { 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var message_var = var_iface_->VarFromUtf8(string, strlen(string)); 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = ki_ioctl_wrapper(fd, NACL_IOC_HANDLEMESSAGE, &message_var); 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var_iface_->Release(message_var); 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) protected: 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FakePepperInterface ppapi_; 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) KernelProxy kp_; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VarInterface* var_iface_; 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}; 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(TtyNodeTest, InvalidIoctl) { 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 123 is not a valid ioctl request. 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(EINVAL, dev_tty_->Ioctl(123)); 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(TtyNodeTest, TtyInput) { 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Now let's try sending some data over. 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // First we create the message. 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string message("hello, how are you?\n"); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) VarInterface* var_iface = ppapi_.GetVarInterface(); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var message_var = var_iface->VarFromUtf8(message.data(), message.size()); 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Now we make buffer we'll read into. 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We fill the buffer and a backup buffer with arbitrary data 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // and compare them after reading to make sure read doesn't 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // clobber parts of the buffer it shouldn't. 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int bytes_read; 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) char buffer[100]; 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) char backup_buffer[100]; 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) memset(buffer, 'a', 100); 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) memset(backup_buffer, 'a', 100); 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Now we actually send the data 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ(0, dev_tty_->Ioctl(NACL_IOC_HANDLEMESSAGE, &message_var)); 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var_iface->Release(message_var); 1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We read a small chunk first to ensure it doesn't give us 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // more than we ask for. 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HandleAttr attrs; 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0, dev_tty_->Read(attrs, buffer, 5, &bytes_read)); 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(5, bytes_read); 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(0, memcmp(message.data(), buffer, 5)); 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(0, memcmp(buffer + 5, backup_buffer + 5, 95)); 1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Now we ask for more data than is left in the tty, to ensure 1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // it doesn't give us more than is there. 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0, dev_tty_->Read(attrs, buffer + 5, 95, &bytes_read)); 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(bytes_read, message.size() - 5); 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(0, memcmp(message.data(), buffer, message.size())); 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(0, memcmp(buffer + message.size(), 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) backup_buffer + message.size(), 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 100 - message.size())); 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)struct user_data_t { 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const char* output_buf; 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t output_count; 1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)static ssize_t output_handler(const char* buf, size_t count, void* data) { 1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data_t* user_data = static_cast<user_data_t*>(data); 1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data->output_buf = buf; 1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data->output_count = count; 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return count; 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(TtyNodeTest, TtyOutput) { 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // When no handler is registered then all writes should return EIO 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int bytes_written = 10; 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const char* message = "hello\n"; 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int message_len = strlen(message); 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HandleAttr attrs; 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(EIO, dev_tty_->Write(attrs, message, message_len, &bytes_written)); 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Setup output handler with user_data to record calls. 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data_t user_data; 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data.output_buf = NULL; 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) user_data.output_count = 0; 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) tioc_nacl_output handler; 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) handler.handler = output_handler; 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) handler.user_data = &user_data; 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0, dev_tty_->Ioctl(TIOCNACLOUTPUT, &handler)); 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0, dev_tty_->Write(attrs, message, message_len, &bytes_written)); 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(message_len, bytes_written); 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(message_len, user_data.output_count); 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(0, strncmp(user_data.output_buf, message, message_len)); 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Returns: 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// 0 -> Not readable 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// 1 -> Readable 1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// -1 -> Error occured 1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)static int IsReadable(int fd) { 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct timeval timeout = {0, 0}; 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fd_set readfds; 1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fd_set errorfds; 1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&readfds); 1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&errorfds); 1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(fd, &readfds); 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(fd, &errorfds); 1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int rtn = ki_select(fd + 1, &readfds, NULL, &errorfds, &timeout); 1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (rtn == 0) 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; // not readable 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (rtn != 1) 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return -1; // error 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (FD_ISSET(fd, &errorfds)) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return -2; // error 1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!FD_ISSET(fd, &readfds)) 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return -3; // error 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 1; // readable 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_F(TtyTest, TtySelect) { 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) struct timeval timeout; 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fd_set readfds; 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fd_set writefds; 1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) fd_set errorfds; 1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tty_fd = ki_open("/dev/tty", O_RDONLY, 0); 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_GT(tty_fd, 0) << "tty open failed: " << errno; 1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&readfds); 1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&errorfds); 1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(tty_fd, &readfds); 1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(tty_fd, &errorfds); 1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // 10 millisecond timeout 1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) timeout.tv_sec = 0; 2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) timeout.tv_usec = 10 * 1000; 2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Should timeout when no input is available. 2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int rtn = ki_select(tty_fd + 1, &readfds, NULL, &errorfds, &timeout); 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, rtn) << "select failed: " << rtn << " err=" << strerror(errno); 2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_FALSE(FD_ISSET(tty_fd, &readfds)); 2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_FALSE(FD_ISSET(tty_fd, &errorfds)); 2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&readfds); 2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&writefds); 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_ZERO(&errorfds); 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(tty_fd, &readfds); 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(tty_fd, &writefds); 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FD_SET(tty_fd, &errorfds); 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TTY should be writable on startup. 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) rtn = ki_select(tty_fd + 1, &readfds, &writefds, &errorfds, NULL); 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1, rtn); 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_TRUE(FD_ISSET(tty_fd, &writefds)); 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_FALSE(FD_ISSET(tty_fd, &readfds)); 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_FALSE(FD_ISSET(tty_fd, &errorfds)); 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Send 4 bytes to TTY input 22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(0, TtyWrite(tty_fd, "input:test")); 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TTY should not be readable until newline in written 2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ASSERT_EQ(IsReadable(tty_fd), 0); 22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(0, TtyWrite(tty_fd, "input:\n")); 2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TTY should now be readable 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1, IsReadable(tty_fd)); 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ki_close(tty_fd); 2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(TtyTest, TtyICANON) { 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tty_fd = ki_open("/dev/tty", O_RDONLY, 0); 23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, IsReadable(tty_fd)); 23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct termios tattr; 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ki_tcgetattr(tty_fd, &tattr); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tattr.c_lflag &= ~(ICANON | ECHO); /* Clear ICANON and ECHO. */ 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ki_tcsetattr(tty_fd, TCSAFLUSH, &tattr); 24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, IsReadable(tty_fd)); 24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Set some bytes to the TTY, not including newline 24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(0, TtyWrite(tty_fd, "a")); 24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Since we are not in canonical mode the bytes should be 24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // immediately readable. 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1, IsReadable(tty_fd)); 25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Read byte from tty. 25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) char c; 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(1, ki_read(tty_fd, &c, 1)); 25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ('a', c); 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, IsReadable(tty_fd)); 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static int g_received_signal; 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void sighandler(int sig) { g_received_signal = sig; } 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)TEST_F(TtyTest, WindowSize) { 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Get current window size 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct winsize old_winsize = {0}; 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tty_fd = ki_open("/dev/tty", O_RDONLY, 0); 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ASSERT_EQ(0, ki_ioctl_wrapper(tty_fd, TIOCGWINSZ, &old_winsize)); 2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Install signal handler 2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sighandler_t new_handler = sighandler; 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sighandler_t old_handler = ki_signal(SIGWINCH, new_handler); 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_NE(SIG_ERR, old_handler) << "signal return error: " << errno; 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 275010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) g_received_signal = 0; 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Set a new windows size 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) struct winsize winsize; 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) winsize.ws_col = 100; 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) winsize.ws_row = 200; 281010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(0, ki_ioctl_wrapper(tty_fd, TIOCSWINSZ, &winsize)); 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(SIGWINCH, g_received_signal); 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Restore old signal handler 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) EXPECT_EQ(new_handler, ki_signal(SIGWINCH, old_handler)); 2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Verify new window size can be queried correctly. 2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) winsize.ws_col = 0; 2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) winsize.ws_row = 0; 290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(0, ki_ioctl_wrapper(tty_fd, TIOCGWINSZ, &winsize)); 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(100, winsize.ws_col); 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(200, winsize.ws_row); 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Restore original windows size. 295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(0, ki_ioctl_wrapper(tty_fd, TIOCSWINSZ, &old_winsize)); 2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/* 29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Sleep for 50ms then send a resize event to /dev/tty. 30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static void* resize_thread_main(void* arg) { 30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usleep(50 * 1000); 30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int* tty_fd = static_cast<int*>(arg); 30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct winsize winsize; 30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) winsize.ws_col = 100; 30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) winsize.ws_row = 200; 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ki_ioctl_wrapper(*tty_fd, TIOCSWINSZ, &winsize); 30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return NULL; 31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(TtyTest, ResizeDuringSelect) { 31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Test that a window resize during a call 31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // to select(3) will cause it to fail with EINTR. 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tty_fd = ki_open("/dev/tty", O_RDONLY, 0); 31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fd_set readfds; 31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fd_set errorfds; 31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_ZERO(&readfds); 32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_ZERO(&errorfds); 32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_SET(tty_fd, &readfds); 32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_SET(tty_fd, &errorfds); 32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pthread_t resize_thread; 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pthread_create(&resize_thread, NULL, resize_thread_main, &tty_fd); 32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct timeval timeout; 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) timeout.tv_sec = 20; 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) timeout.tv_usec = 0; 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TTY should not be readable either before or after the 33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // call to select(3). 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, IsReadable(tty_fd)); 33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int rtn = ki_select(tty_fd + 1, &readfds, NULL, &errorfds, &timeout); 33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pthread_join(resize_thread, NULL); 33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(-1, rtn); 33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(EINTR, errno); 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ(0, IsReadable(tty_fd)); 34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/* 34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) * Sleep for 50ms then send some input to the /dev/tty. 34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) */ 34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static void* input_thread_main(void* arg) { 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TtyTest* thiz = static_cast<TtyTest*>(arg); 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usleep(50 * 1000); 34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int fd = ki_open("/dev/tty", O_RDONLY, 0); 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) thiz->TtyWrite(fd, "test\n"); 35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return NULL; 35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(TtyTest, InputDuringSelect) { 35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Test that input which occurs while in select causes 35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // select to return. 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tty_fd = ki_open("/dev/tty", O_RDONLY, 0); 35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fd_set readfds; 36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) fd_set errorfds; 36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_ZERO(&readfds); 36368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_ZERO(&errorfds); 36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_SET(tty_fd, &readfds); 36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FD_SET(tty_fd, &errorfds); 36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pthread_t resize_thread; 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pthread_create(&resize_thread, NULL, input_thread_main, this); 36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) struct timeval timeout; 37168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) timeout.tv_sec = 20; 37268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) timeout.tv_usec = 0; 37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 37468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int rtn = ki_select(tty_fd + 1, &readfds, NULL, &errorfds, &timeout); 37568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pthread_join(resize_thread, NULL); 37668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_EQ(1, rtn); 37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 381