GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_report_utils.cc Lines: 126 145 86.9 %
Date: 2019-10-05 22:32:21 Branches: 62 91 68.1 %

Line Branch Exec Source
1
#include "node_internals.h"
2
#include "node_report.h"
3
#include "util-inl.h"
4
5
namespace report {
6
7
using node::MallocedBuffer;
8
9
static constexpr auto null = JSONWriter::Null{};
10
11
// Utility function to format socket information.
12
10
static void ReportEndpoint(uv_handle_t* h,
13
                           struct sockaddr* addr,
14
                           const char* name,
15
                           JSONWriter* writer) {
16
10
  if (addr == nullptr) {
17
2
    writer->json_keyvalue(name, null);
18
12
    return;
19
  }
20
21
  uv_getnameinfo_t endpoint;
22
8
  char* host = nullptr;
23
  char hostbuf[INET6_ADDRSTRLEN];
24
8
  const int family = addr->sa_family;
25
  const int port = ntohs(family == AF_INET ?
26
                         reinterpret_cast<sockaddr_in*>(addr)->sin_port :
27
8
                         reinterpret_cast<sockaddr_in6*>(addr)->sin6_port);
28
29
8
  if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
30
8
    host = endpoint.host;
31
    DCHECK_EQ(port, std::stoi(endpoint.service));
32
  } else {
33
    const void* src = family == AF_INET ?
34
                      static_cast<void*>(
35
                        &(reinterpret_cast<sockaddr_in*>(addr)->sin_addr)) :
36
                      static_cast<void*>(
37
                        &(reinterpret_cast<sockaddr_in6*>(addr)->sin6_addr));
38
    if (uv_inet_ntop(family, src, hostbuf, sizeof(hostbuf)) == 0) {
39
      host = hostbuf;
40
    }
41
  }
42
8
  writer->json_objectstart(name);
43
8
  if (host != nullptr) {
44
8
    writer->json_keyvalue("host", host);
45
  }
46
8
  writer->json_keyvalue("port", port);
47
8
  writer->json_objectend();
48
}
49
50
// Utility function to format libuv socket information.
51
5
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
52
  struct sockaddr_storage addr_storage;
53
5
  struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
54
5
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
55
5
  int addr_size = sizeof(addr_storage);
56
5
  int rc = -1;
57
58
5
  switch (h->type) {
59
    case UV_UDP:
60
2
      rc = uv_udp_getsockname(&handle->udp, addr, &addr_size);
61
2
      break;
62
    case UV_TCP:
63
3
      rc = uv_tcp_getsockname(&handle->tcp, addr, &addr_size);
64
3
      break;
65
    default:
66
      break;
67
  }
68
5
  ReportEndpoint(h, rc == 0 ? addr : nullptr,  "localEndpoint", writer);
69
70
5
  switch (h->type) {
71
    case UV_UDP:
72
2
      rc = uv_udp_getpeername(&handle->udp, addr, &addr_size);
73
2
      break;
74
    case UV_TCP:
75
3
      rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size);
76
3
      break;
77
    default:
78
      break;
79
  }
80
5
  ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer);
81
5
}
82
83
// Utility function to format libuv path information.
84
2
static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
85
2
  MallocedBuffer<char> buffer(0);
86
2
  int rc = -1;
87
2
  size_t size = 0;
88
2
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
89
2
  bool wrote_filename = false;
90
  // First call to get required buffer size.
91
2
  switch (h->type) {
92
    case UV_FS_EVENT:
93
1
      rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
94
1
      break;
95
    case UV_FS_POLL:
96
1
      rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
97
1
      break;
98
    default:
99
      break;
100
  }
101
2
  if (rc == UV_ENOBUFS) {
102
2
    buffer = MallocedBuffer<char>(size + 1);
103
2
    switch (h->type) {
104
      case UV_FS_EVENT:
105
1
        rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
106
1
        break;
107
      case UV_FS_POLL:
108
1
        rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
109
1
        break;
110
      default:
111
        break;
112
    }
113
2
    if (rc == 0) {
114
      // buffer is not null terminated.
115
2
      buffer.data[size] = '\0';
116
2
      writer->json_keyvalue("filename", buffer.data);
117
2
      wrote_filename = true;
118
    }
119
  }
120
2
  if (!wrote_filename) writer->json_keyvalue("filename", null);
121
2
}
122
123
// Utility function to walk libuv handles.
124
135
void WalkHandle(uv_handle_t* h, void* arg) {
125
135
  const char* type = uv_handle_type_name(h->type);
126
135
  JSONWriter* writer = static_cast<JSONWriter*>(arg);
127
135
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
128
129
135
  writer->json_start();
130
135
  writer->json_keyvalue("type", type);
131
135
  writer->json_keyvalue("is_active", static_cast<bool>(uv_is_active(h)));
132
135
  writer->json_keyvalue("is_referenced", static_cast<bool>(uv_has_ref(h)));
133
  writer->json_keyvalue("address",
134
135
                        ValueToHexString(reinterpret_cast<uint64_t>(h)));
135
136

135
  switch (h->type) {
137
    case UV_FS_EVENT:
138
    case UV_FS_POLL:
139
2
      ReportPath(h, writer);
140
2
      break;
141
    case UV_PROCESS:
142
1
      writer->json_keyvalue("pid", handle->process.pid);
143
1
      break;
144
    case UV_TCP:
145
    case UV_UDP:
146
5
      ReportEndpoints(h, writer);
147
5
      break;
148
    case UV_TIMER: {
149
17
      uint64_t due = handle->timer.timeout;
150
17
      uint64_t now = uv_now(handle->timer.loop);
151
17
      writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer));
152
      writer->json_keyvalue("firesInMsFromNow",
153
17
                            static_cast<int64_t>(due - now));
154
17
      writer->json_keyvalue("expired", now >= due);
155
17
      break;
156
    }
157
    case UV_TTY: {
158
      int height, width, rc;
159
      rc = uv_tty_get_winsize(&(handle->tty), &width, &height);
160
      if (rc == 0) {
161
        writer->json_keyvalue("width", width);
162
        writer->json_keyvalue("height", height);
163
      }
164
      break;
165
    }
166
    case UV_SIGNAL:
167
      // SIGWINCH is used by libuv so always appears.
168
      // See http://docs.libuv.org/en/v1.x/signal.html
169
1
      writer->json_keyvalue("signum", handle->signal.signum);
170
      writer->json_keyvalue("signal",
171
1
                            node::signo_string(handle->signal.signum));
172
1
      break;
173
    default:
174
109
      break;
175
  }
176
177

135
  if (h->type == UV_TCP || h->type == UV_UDP
178
#ifndef _WIN32
179
130
      || h->type == UV_NAMED_PIPE
180
#endif
181
  ) {
182
    // These *must* be 0 or libuv will set the buffer sizes to the non-zero
183
    // values they contain.
184
9
    int send_size = 0;
185
9
    int recv_size = 0;
186
9
    uv_send_buffer_size(h, &send_size);
187
9
    uv_recv_buffer_size(h, &recv_size);
188
9
    writer->json_keyvalue("sendBufferSize", send_size);
189
9
    writer->json_keyvalue("recvBufferSize", recv_size);
190
  }
191
192
#ifndef _WIN32
193


263
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY ||
194
254
      h->type == UV_UDP || h->type == UV_POLL) {
195
    uv_os_fd_t fd_v;
196
9
    int rc = uv_fileno(h, &fd_v);
197
198
9
    if (rc == 0) {
199
9
      writer->json_keyvalue("fd", static_cast<int>(fd_v));
200

9
      switch (fd_v) {
201
        case STDIN_FILENO:
202
          writer->json_keyvalue("stdio", "stdin");
203
          break;
204
        case STDOUT_FILENO:
205
          writer->json_keyvalue("stdio", "stdout");
206
          break;
207
        case STDERR_FILENO:
208
          writer->json_keyvalue("stdio", "stderr");
209
          break;
210
        default:
211
9
          break;
212
      }
213
    }
214
  }
215
#endif
216
217

135
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY) {
218
7
    writer->json_keyvalue("writeQueueSize", handle->stream.write_queue_size);
219
    writer->json_keyvalue("readable",
220
7
                          static_cast<bool>(uv_is_readable(&handle->stream)));
221
    writer->json_keyvalue("writable",
222
7
                          static_cast<bool>(uv_is_writable(&handle->stream)));
223
  }
224
225
135
  writer->json_end();
226
135
}
227
228
8620
std::string EscapeJsonChars(const std::string& str) {
229
  const std::string control_symbols[0x20] = {
230
      "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
231
      "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r",
232
      "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013",
233
      "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019",
234
      "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"
235
284460
  };
236
237
8620
  std::string ret;
238
8620
  size_t last_pos = 0;
239
8620
  size_t pos = 0;
240
125703
  for (; pos < str.size(); ++pos) {
241
117083
    std::string replace;
242
117083
    char ch = str[pos];
243
117083
    if (ch == '\\') {
244
      replace = "\\\\";
245
117083
    } else if (ch == '\"') {
246
4
      replace = "\\\"";
247
    } else {
248
117079
      size_t num = static_cast<size_t>(ch);
249
117079
      if (num < 0x20) replace = control_symbols[num];
250
    }
251
117083
    if (!replace.empty()) {
252
4
      if (pos > last_pos) {
253
4
        ret += str.substr(last_pos, pos - last_pos);
254
      }
255
4
      last_pos = pos + 1;
256
4
      ret += replace;
257
    }
258
117083
  }
259
  // Append any remaining symbols.
260
8620
  if (last_pos < str.size()) {
261
8605
    ret += str.substr(last_pos, pos - last_pos);
262
  }
263
284460
  return ret;
264
}
265
266

14832
}  // namespace report