Skip to content

Commit 113fe6a

Browse files
committed
Initial implementation of the |close()|, |connect()| and |socket()|
functions.
1 parent 93288fc commit 113fe6a

28 files changed

+679
-9
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@
2828
*.app
2929

3030
/out
31+
/*.creator.user*

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "src/third_party/elf_hook/exported"]
2+
path = src/third_party/elf_hook/exported
3+
url = https://github.com/shoumikhin/ELF-Hook.git

BUILD.gn

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
group("All") {
2-
deps = [ "//src:mock_network" ]
2+
deps = [ "//src/mock_network:mock_network" ]
33
}
44

55
if (config_for_tests) {
66
group("Tests") {
7-
deps = []
7+
testonly = true
8+
9+
deps = [ "//src/test:unit_tests" ]
810
}
911
}

build/config/linux/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ config("base") {
55

66
ldflags = [
77
"--no-undefined",
8+
"-pthread",
89
"-rdynamic", # for |backtrace()|
910
"-rpath", "\$ORIGIN",
1011
]

mock-network.files

+49-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,53 @@ build/config/BUILD.gn
33
build/config/BUILDCONFIG.gn
44
build/toolchain/linux/BUILD.gn
55
build/version.py
6-
src/BUILD.gn
7-
src/main.cc
6+
src/base/aliases.h
7+
src/base/c_utils.h
8+
src/mock_network/BUILD.gn
9+
src/mock_network/mock.cc
10+
src/mock_network/mock.h
11+
src/third_party/elf_hook/exported/elf_hook.c
12+
src/third_party/elf_hook/exported/elf_hook.h
13+
src/third_party/elf_hook/BUILD.gn
14+
src/third_party/gtest/exported/include/gtest/internal/gtest-death-test-internal.h
15+
src/third_party/gtest/exported/include/gtest/internal/gtest-filepath.h
16+
src/third_party/gtest/exported/include/gtest/internal/gtest-internal.h
17+
src/third_party/gtest/exported/include/gtest/internal/gtest-linked_ptr.h
18+
src/third_party/gtest/exported/include/gtest/internal/gtest-param-util-generated.h
19+
src/third_party/gtest/exported/include/gtest/internal/gtest-param-util.h
20+
src/third_party/gtest/exported/include/gtest/internal/gtest-port.h
21+
src/third_party/gtest/exported/include/gtest/internal/gtest-string.h
22+
src/third_party/gtest/exported/include/gtest/internal/gtest-tuple.h
23+
src/third_party/gtest/exported/include/gtest/internal/gtest-type-util.h
24+
src/third_party/gtest/exported/include/gtest/gtest-death-test.h
25+
src/third_party/gtest/exported/include/gtest/gtest-message.h
26+
src/third_party/gtest/exported/include/gtest/gtest-param-test.h
27+
src/third_party/gtest/exported/include/gtest/gtest-printers.h
28+
src/third_party/gtest/exported/include/gtest/gtest-spi.h
29+
src/third_party/gtest/exported/include/gtest/gtest-test-part.h
30+
src/third_party/gtest/exported/include/gtest/gtest-typed-test.h
31+
src/third_party/gtest/exported/include/gtest/gtest.h
32+
src/third_party/gtest/exported/include/gtest/gtest_pred_impl.h
33+
src/third_party/gtest/exported/include/gtest/gtest_prod.h
34+
src/third_party/gtest/exported/src/gtest-death-test.cc
35+
src/third_party/gtest/exported/src/gtest-filepath.cc
36+
src/third_party/gtest/exported/src/gtest-internal-inl.h
37+
src/third_party/gtest/exported/src/gtest-port.cc
38+
src/third_party/gtest/exported/src/gtest-printers.cc
39+
src/third_party/gtest/exported/src/gtest-test-part.cc
40+
src/third_party/gtest/exported/src/gtest-typed-test.cc
41+
src/third_party/gtest/exported/src/gtest.cc
42+
src/third_party/gtest/exported/src/gtest_main.cc
43+
src/third_party/gtest/BUILD.gn
844
BUILD.gn
45+
src/test/run_all_tests.cc
46+
src/test/BUILD.gn
47+
src/mock_network/mock_test.cc
48+
src/mock_network/test_library.cc
49+
src/mock_network/test_library.h
50+
src/mock_network/functions.cc
51+
src/mock_network/functions.h
52+
src/mock_network/socket.h
53+
src/mock_network/socket.cc
54+
src/mock_network/connect.h
55+
src/mock_network/connect.cc

mock-network.includes

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
src
2+
src/third_party/gtest/exported/include
3+
src/mock_network

src/BUILD.gn

-3
This file was deleted.

src/base/aliases.h

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#pragma once
2+
3+
#include <atomic>
4+
#include <list>
5+
#include <memory>
6+
#include <mutex>
7+
#include <set>
8+
#include <string>
9+
#include <unordered_map>
10+
#include <unordered_set>
11+
#include <vector>
12+
13+
template <class T>
14+
using Atomic = std::atomic<T>;
15+
16+
template <class T>
17+
using List = std::list<T>;
18+
19+
using String = std::string;
20+
21+
template <class U, class V>
22+
using Map = std::unordered_map<U, V>;
23+
24+
using Mutex = std::mutex;
25+
26+
template <class T>
27+
using Set = std::set<T>;
28+
29+
using UniqueLock = std::unique_lock<Mutex>;
30+
31+
template <class U, class V>
32+
using UniquePtr = std::unique_ptr<U, V>;
33+
34+
template <class U, class V>
35+
using HashMap = std::unordered_map<U, V>;
36+
37+
template <class T>
38+
using HashSet = std::unordered_set<T>;
39+
40+
template <class T>
41+
using Vector = std::vector<T>;

src/base/c_utils.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <base/aliases.h>
4+
5+
#include <cerrno>
6+
#include <cstring>
7+
8+
namespace mock_network {
9+
namespace base {
10+
11+
void GetLastError(String* error, String prefix = String()) {
12+
if (error) {
13+
error->assign(strerror(errno));
14+
if (!prefix.empty()) {
15+
error->assign(prefix + ": " + *error);
16+
}
17+
}
18+
}
19+
20+
} // namespace base
21+
} // namespace mock_network

src/main.cc

-2
This file was deleted.

src/mock_network/BUILD.gn

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
shared_library("mock_network") {
2+
sources = [
3+
"connect.cc",
4+
"connect.h",
5+
"functions.cc",
6+
"functions.h",
7+
"mock.cc",
8+
"mock.h",
9+
"socket.cc",
10+
"socket.h",
11+
]
12+
13+
public = [
14+
"connect.h",
15+
"mock.h",
16+
]
17+
18+
deps += [ "//src/third_party/elf_hook:elf_hook" ]
19+
20+
libs = [ "dl" ]
21+
}
22+
23+
shared_library("test_library") {
24+
testonly = true
25+
26+
sources = [
27+
"test_library.cc",
28+
"test_library.h",
29+
]
30+
}

src/mock_network/connect.cc

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <mock_network/connect.h>
2+
3+
namespace mock_network {
4+
5+
std::chrono::seconds connection_duration(0);
6+
int connection_result = 0;
7+
8+
void SetConnectionDuration(std::chrono::seconds duration) {
9+
connection_duration = duration;
10+
}
11+
12+
void SetConnectionResult(int error_code) {
13+
connection_result = error_code;
14+
}
15+
16+
} // namespace mock_network

src/mock_network/connect.h

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include <chrono>
4+
5+
namespace mock_network {
6+
7+
void SetConnectionDuration(std::chrono::seconds duration);
8+
void SetConnectionResult(int error_code);
9+
10+
} // namespace mock_network

src/mock_network/functions.cc

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <mock_network/functions.h>
2+
3+
#include <mock_network/socket.h>
4+
5+
#include <thread>
6+
7+
#include <errno.h>
8+
#include <unistd.h>
9+
10+
namespace mock_network {
11+
12+
extern std::chrono::seconds connection_duration;
13+
extern int connection_result;
14+
extern Map<String, void*> originals;
15+
16+
namespace fake {
17+
18+
int close(int fd) {
19+
Socket socket = Socket::Get(fd);
20+
if (socket.IsValid()) {
21+
return socket.Close();
22+
}
23+
24+
return reinterpret_cast<int (*)(int)>(originals["close"])(fd);
25+
}
26+
27+
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen) {
28+
Socket socket = Socket::Get(sockfd);
29+
if (!socket.IsValid()) {
30+
// We can't detect, if the |sockfd| is a valid descriptor at a system level,
31+
// so we always indicate that it's just not a socket.
32+
errno = ENOTSOCK;
33+
return -1;
34+
}
35+
36+
if (!socket.SetState(Socket::CONNECTING)) {
37+
if (socket.GetState() == Socket::CONNECTING) {
38+
errno = EALREADY;
39+
} else if (socket.GetState() >= Socket::CONNECTED) {
40+
errno = EISCONN;
41+
}
42+
43+
return -1;
44+
}
45+
46+
if (!socket.IsNonBlocking()) {
47+
std::this_thread::sleep_for(connection_duration);
48+
// TODO: handle peer address.
49+
socket.SetState(Socket::CONNECTED);
50+
} else {
51+
// TODO: implement non-blocking connection, keeping in mind, that |select()|
52+
// or |epoll()| should somehow indicate this fact using pipes.
53+
// TODO: return EINPROGRESS, if the |connection_duration| is non-zero.
54+
}
55+
56+
if (connection_result == 0) {
57+
return 0;
58+
} else {
59+
errno = connection_result;
60+
return -1;
61+
}
62+
}
63+
64+
int socket(int domain, int type, int protocol) {
65+
// We work only with predefined combinations of params.
66+
if ((domain != AF_UNIX && domain != AF_INET && domain != AF_INET6) ||
67+
(type & SOCK_STREAM) != SOCK_STREAM || protocol != 0) {
68+
errno = EINVAL;
69+
return -1;
70+
}
71+
72+
return Socket(domain, type, protocol);
73+
}
74+
75+
} // namespace fake
76+
} // namespace mock_network

src/mock_network/functions.h

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <sys/socket.h>
4+
5+
namespace mock_network {
6+
namespace fake {
7+
8+
int close(int fd);
9+
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
10+
int socket(int domain, int type, int protocol);
11+
12+
} // namespace fake
13+
} // namespace mock_network

0 commit comments

Comments
 (0)