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-05-05 22:32:45 Branches: 62 91 68.1 %

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

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

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


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

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

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

13575
}  // namespace report