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: 143 162 88.3 %
Date: 2020-02-19 22:14:06 Branches: 69 95 72.6 %

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
2
    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
16
  const int port = ntohs(family == AF_INET ?
26
5
                         reinterpret_cast<sockaddr_in*>(addr)->sin_port :
27
11
                         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
4
  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
177
void WalkHandle(uv_handle_t* h, void* arg) {
125
177
  const char* type = uv_handle_type_name(h->type);
126
177
  JSONWriter* writer = static_cast<JSONWriter*>(arg);
127
177
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
128
129
177
  writer->json_start();
130
177
  writer->json_keyvalue("type", type);
131
177
  writer->json_keyvalue("is_active", static_cast<bool>(uv_is_active(h)));
132
177
  writer->json_keyvalue("is_referenced", static_cast<bool>(uv_has_ref(h)));
133
  writer->json_keyvalue("address",
134
177
                        ValueToHexString(reinterpret_cast<uint64_t>(h)));
135
136

177
  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
25
      uint64_t due = handle->timer.timeout;
150
25
      uint64_t now = uv_now(handle->timer.loop);
151
25
      writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer));
152
      writer->json_keyvalue("firesInMsFromNow",
153
25
                            static_cast<int64_t>(due - now));
154
25
      writer->json_keyvalue("expired", now >= due);
155
25
      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
143
      break;
175
  }
176
177

177
  if (h->type == UV_TCP || h->type == UV_UDP
178
#ifndef _WIN32
179
172
      || 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


347
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY ||
194
338
      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

177
  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
177
  writer->json_end();
226
177
}
227
228
11141
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
22282
  };
236
237
11141
  std::string ret;
238
11141
  size_t last_pos = 0;
239
11141
  size_t pos = 0;
240
309321
  for (; pos < str.size(); ++pos) {
241
298180
    std::string replace;
242
149090
    char ch = str[pos];
243
149090
    if (ch == '\\') {
244
1
      replace = "\\\\";
245
149089
    } else if (ch == '\"') {
246
5
      replace = "\\\"";
247
    } else {
248
149084
      size_t num = static_cast<size_t>(ch);
249
149084
      if (num < 0x20) replace = control_symbols[num];
250
    }
251
149090
    if (!replace.empty()) {
252
72
      if (pos > last_pos) {
253
40
        ret += str.substr(last_pos, pos - last_pos);
254
      }
255
72
      last_pos = pos + 1;
256
72
      ret += replace;
257
    }
258
  }
259
  // Append any remaining symbols.
260
11141
  if (last_pos < str.size()) {
261
11053
    ret += str.substr(last_pos, pos - last_pos);
262
  }
263
22282
  return ret;
264
}
265
266
2
std::string Reindent(const std::string& str, int indent_depth) {
267
4
  std::string indent;
268
2
  for (int i = 0; i < indent_depth; i++) indent += ' ';
269
270
2
  std::string out;
271
2
  std::string::size_type pos = 0;
272
  do {
273
1028
    std::string::size_type prev_pos = pos;
274
1028
    pos = str.find('\n', pos);
275
276
1028
    out.append(indent);
277
278
1028
    if (pos == std::string::npos) {
279
2
      out.append(str, prev_pos, std::string::npos);
280
2
      break;
281
    } else {
282
1026
      pos++;
283
1026
      out.append(str, prev_pos, pos - prev_pos);
284
1026
    }
285
  } while (true);
286
287
4
  return out;
288
}
289
290

12558
}  // namespace report