The main posixpp library and associated tests.
Revision | 2737e23040266d8ffd8a569d1859da2b91cc1a48 (tree) |
---|---|
Time | 2021-04-30 01:31:13 |
Author | Eric Hopper <hopper@omni...> |
Commiter | Eric Hopper |
Tests for dup and dup2.
@@ -67,3 +67,106 @@ | ||
67 | 67 | } |
68 | 68 | } |
69 | 69 | } |
70 | + | |
71 | +SCENARIO( | |
72 | + "File descriptor objects have dup and dup2 methods that work as expected." | |
73 | +) { | |
74 | + GIVEN( | |
75 | + "A new opened file foo in a new temporary directory containing " | |
76 | + "some known text." | |
77 | + ) { | |
78 | + tempdir testdir; | |
79 | + static const char known_text[] = "This is just some known text."; | |
80 | + auto fooname = testdir.get_name() / "foo"; | |
81 | + using ::posixpp::fd; | |
82 | + using of = ::posixpp::openflags; | |
83 | + using fdf = ::posixpp::fdflags; | |
84 | + using ::posixpp::modeflags; | |
85 | + auto foo{ | |
86 | + fd::open( | |
87 | + fooname.native().c_str(), | |
88 | + of::creat | fdf::wronly, | |
89 | + modeflags::irwall | |
90 | + ).result() | |
91 | + }; | |
92 | + // Don't write out the trailing '\0'; | |
93 | + REQUIRE(foo.write(known_text, sizeof(known_text) - 1).result() == sizeof(known_text) - 1); | |
94 | + foo.close().throw_if_error(); | |
95 | + foo = fd::open(fooname.native().c_str(), fdf::rdonly).result(); | |
96 | + WHEN("The foo.dup() is called.") { | |
97 | + fd bar{ foo.dup().result() }; | |
98 | + | |
99 | + THEN("It results in a new valid file descriptor.") { | |
100 | + REQUIRE(bar.is_valid()); | |
101 | + REQUIRE(foo.as_fd() != bar.as_fd()); | |
102 | + } | |
103 | + AND_WHEN("You read one character from it.") { | |
104 | + char buf[1]; | |
105 | + REQUIRE(bar.read(buf, 1).result() == 1); | |
106 | + THEN("you read the first character of the known text.") { | |
107 | + REQUIRE(buf[0] == known_text[0]); | |
108 | + } | |
109 | + AND_WHEN("you then read one character from the original fd.") { | |
110 | + char buf2[1]; | |
111 | + REQUIRE(foo.read(buf2, 1).result() == 1); | |
112 | + THEN("that character is the second character of the known text.") { | |
113 | + REQUIRE(buf2[0] == known_text[1]); | |
114 | + } | |
115 | + } | |
116 | + } | |
117 | + } | |
118 | + WHEN("foo.dup2(foo) is called.") { | |
119 | + REQUIRE_NOTHROW(foo.dup2(foo).throw_if_error()); | |
120 | + THEN("foo is still valid") { | |
121 | + REQUIRE(foo.is_valid()); | |
122 | + } | |
123 | + THEN( "a byte read from foo is the first byte of known_text") { | |
124 | + char buf_foo[1]; | |
125 | + REQUIRE(foo.read(buf_foo, 1).result() == 1); | |
126 | + REQUIRE(buf_foo[0] == known_text[0]); | |
127 | + } | |
128 | + } | |
129 | + AND_GIVEN("Another file descriptor opened on the same file.") { | |
130 | + auto foo2{fd::open(fooname.native().c_str(), fdf::rdonly).result()}; | |
131 | + THEN("It is valid.") { | |
132 | + REQUIRE(foo2.is_valid()); | |
133 | + } | |
134 | + WHEN( | |
135 | + "One byte is read from each" | |
136 | + ) { | |
137 | + // Initialize to 0 to make sure they change when read into. | |
138 | + char buf_foo[1] = {}; | |
139 | + char buf_foo2[1] = {}; | |
140 | + REQUIRE(foo.read(buf_foo, 1).result() == 1); | |
141 | + REQUIRE(foo2.read(buf_foo2, 1).result() == 1); | |
142 | + THEN( | |
143 | + "it's the same byte, and the first byte of the known " | |
144 | + "text, demonstrating that they each refer to a different " | |
145 | + "underlying file descriptor." | |
146 | + ) { | |
147 | + REQUIRE(buf_foo2[0] == known_text[0]); | |
148 | + REQUIRE(buf_foo[0] == buf_foo2[0]); | |
149 | + } AND_WHEN("we dup2 the first fd to the second fd") { | |
150 | + foo.dup2(foo2).throw_if_error(); | |
151 | + THEN("foo2 is still valid, and can be closed") { | |
152 | + REQUIRE(foo2.is_valid()); | |
153 | + REQUIRE_NOTHROW(foo2.close().throw_if_error()); | |
154 | + } AND_WHEN ("we then read read a byte from each file.") { | |
155 | + char buff2_foo[1]; | |
156 | + char buf2_foo2[1]; | |
157 | + REQUIRE(foo.read(buff2_foo, 1).result() == 1); | |
158 | + REQUIRE(foo2.read(buf2_foo2, 1).result() == 1); | |
159 | + THEN( | |
160 | + "then we get the 2nd and 3rd bytes of known " | |
161 | + "text, demonstrating they now refer to the same " | |
162 | + "underlying file descriptor." | |
163 | + ) { | |
164 | + REQUIRE(buff2_foo[0] == known_text[1]); | |
165 | + REQUIRE(buf2_foo2[0] == known_text[2]); | |
166 | + } | |
167 | + } | |
168 | + } | |
169 | + } | |
170 | + } | |
171 | + } | |
172 | +} |