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: 114 140 81.4 %
Date: 2019-03-02 22:23:06 Branches: 58 90 64.4 %

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
7
static void ReportEndpoint(uv_handle_t* h,
12
                           struct sockaddr* addr,
13
                           const char* name,
14
                           JSONWriter* writer) {
15
7
  if (addr == nullptr) {
16
1
    writer->json_keyvalue(name, null);
17
8
    return;
18
  }
19
20
  uv_getnameinfo_t endpoint;
21
6
  char* host = nullptr;
22
  char hostbuf[INET6_ADDRSTRLEN];
23
6
  const int family = addr->sa_family;
24
  const int port = ntohs(family == AF_INET ?
25
                         reinterpret_cast<sockaddr_in*>(addr)->sin_port :
26
6
                         reinterpret_cast<sockaddr_in6*>(addr)->sin6_port);
27
28
6
  if (uv_getnameinfo(h->loop, &endpoint, nullptr, addr, NI_NUMERICSERV) == 0) {
29
6
    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
6
  writer->json_objectstart(name);
42
6
  if (host != nullptr) {
43
6
    writer->json_keyvalue("host", host);
44
  }
45
6
  writer->json_keyvalue("port", port);
46
6
  writer->json_objectend();
47
}
48
49
// Utility function to format libuv socket information.
50
4
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
51
  struct sockaddr_storage addr_storage;
52
4
  struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
53
4
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
54
4
  int addr_size = sizeof(addr_storage);
55
4
  int rc = -1;
56
57
4
  switch (h->type) {
58
    case UV_UDP:
59
1
      rc = uv_udp_getsockname(&handle->udp, addr, &addr_size);
60
1
      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
4
  ReportEndpoint(h, rc == 0 ? addr : nullptr,  "localEndpoint", writer);
68
69
4
  if (h->type == UV_TCP) {
70
    // Get the remote end of the connection.
71
3
    rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size);
72
3
    ReportEndpoint(h, rc == 0 ? addr : nullptr, "remoteEndpoint", writer);
73
  }
74
4
}
75
76
// Utility function to format libuv path information.
77
2
static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
78
2
  MallocedBuffer<char> buffer(0);
79
2
  int rc = -1;
80
2
  size_t size = 0;
81
2
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
82
2
  bool wrote_filename = false;
83
  // First call to get required buffer size.
84
2
  switch (h->type) {
85
    case UV_FS_EVENT:
86
1
      rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
87
1
      break;
88
    case UV_FS_POLL:
89
1
      rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
90
1
      break;
91
    default:
92
      break;
93
  }
94
2
  if (rc == UV_ENOBUFS) {
95
2
    buffer = MallocedBuffer<char>(size + 1);
96
2
    switch (h->type) {
97
      case UV_FS_EVENT:
98
1
        rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
99
1
        break;
100
      case UV_FS_POLL:
101
1
        rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
102
1
        break;
103
      default:
104
        break;
105
    }
106
2
    if (rc == 0) {
107
      // buffer is not null terminated.
108
2
      buffer.data[size] = '\0';
109
2
      writer->json_keyvalue("filename", buffer.data);
110
2
      wrote_filename = true;
111
    }
112
  }
113
2
  if (!wrote_filename) writer->json_keyvalue("filename", null);
114
2
}
115
116
// Utility function to walk libuv handles.
117
81
void WalkHandle(uv_handle_t* h, void* arg) {
118
81
  const char* type = uv_handle_type_name(h->type);
119
81
  JSONWriter* writer = static_cast<JSONWriter*>(arg);
120
81
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
121
122
81
  writer->json_start();
123
124

81
  switch (h->type) {
125
    case UV_FS_EVENT:
126
    case UV_FS_POLL:
127
2
      ReportPath(h, writer);
128
2
      break;
129
    case UV_PROCESS:
130
1
      writer->json_keyvalue("pid", handle->process.pid);
131
1
      break;
132
    case UV_TCP:
133
    case UV_UDP:
134
4
      ReportEndpoints(h, writer);
135
4
      break;
136
    case UV_TIMER: {
137
10
      uint64_t due = handle->timer.timeout;
138
10
      uint64_t now = uv_now(handle->timer.loop);
139
10
      writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer));
140
      writer->json_keyvalue("firesInMsFromNow",
141
10
                            static_cast<int64_t>(due - now));
142
10
      writer->json_keyvalue("expired", now >= due);
143
10
      break;
144
    }
145
    case UV_TTY: {
146
      int height, width, rc;
147
      rc = uv_tty_get_winsize(&(handle->tty), &width, &height);
148
      if (rc == 0) {
149
        writer->json_keyvalue("width", width);
150
        writer->json_keyvalue("height", height);
151
      }
152
      break;
153
    }
154
    case UV_SIGNAL:
155
      // SIGWINCH is used by libuv so always appears.
156
      // See http://docs.libuv.org/en/v1.x/signal.html
157
      writer->json_keyvalue("signum", handle->signal.signum);
158
      writer->json_keyvalue("signal",
159
                            node::signo_string(handle->signal.signum));
160
      break;
161
    default:
162
64
      break;
163
  }
164
165

81
  if (h->type == UV_TCP || h->type == UV_UDP
166
#ifndef _WIN32
167
77
      || h->type == UV_NAMED_PIPE
168
#endif
169
  ) {
170
    // These *must* be 0 or libuv will set the buffer sizes to the non-zero
171
    // values they contain.
172
8
    int send_size = 0;
173
8
    int recv_size = 0;
174
8
    uv_send_buffer_size(h, &send_size);
175
8
    uv_recv_buffer_size(h, &recv_size);
176
8
    writer->json_keyvalue("sendBufferSize", send_size);
177
8
    writer->json_keyvalue("recvBufferSize", recv_size);
178
  }
179
180
#ifndef _WIN32
181


155
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY ||
182
147
      h->type == UV_UDP || h->type == UV_POLL) {
183
    uv_os_fd_t fd_v;
184
8
    int rc = uv_fileno(h, &fd_v);
185
186
8
    if (rc == 0) {
187
8
      writer->json_keyvalue("fd", static_cast<int>(fd_v));
188

8
      switch (fd_v) {
189
        case 0:
190
          writer->json_keyvalue("stdio", "stdin");
191
          break;
192
        case 1:
193
          writer->json_keyvalue("stdio", "stdout");
194
          break;
195
        case 2:
196
          writer->json_keyvalue("stdio", "stderr");
197
          break;
198
      }
199
    }
200
  }
201
#endif
202
203

81
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY) {
204
7
    writer->json_keyvalue("writeQueueSize", handle->stream.write_queue_size);
205
    writer->json_keyvalue("readable",
206
7
                          static_cast<bool>(uv_is_readable(&handle->stream)));
207
    writer->json_keyvalue("writable",
208
7
                          static_cast<bool>(uv_is_writable(&handle->stream)));
209
  }
210
211
81
  writer->json_keyvalue("type", type);
212
81
  writer->json_keyvalue("is_active", static_cast<bool>(uv_is_active(h)));
213
81
  writer->json_keyvalue("is_referenced", static_cast<bool>(uv_has_ref(h)));
214
  writer->json_keyvalue("address",
215
81
                        ValueToHexString(reinterpret_cast<uint64_t>(h)));
216
81
  writer->json_end();
217
81
}
218
219
4254
std::string EscapeJsonChars(const std::string& str) {
220
  const std::string control_symbols[0x20] = {
221
      "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
222
      "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r",
223
      "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013",
224
      "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019",
225
      "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"
226
140382
  };
227
228
4254
  std::string ret = "";
229
4254
  size_t last_pos = 0;
230
4254
  size_t pos = 0;
231
69845
  for (; pos < str.size(); ++pos) {
232
65591
    std::string replace;
233
65591
    char ch = str[pos];
234
65591
    if (ch == '\\') {
235
      replace = "\\\\";
236
65591
    } else if (ch == '\"') {
237
      replace = "\\\"";
238
    } else {
239
65591
      size_t num = static_cast<size_t>(ch);
240
65591
      if (num < 0x20) replace = control_symbols[num];
241
    }
242
65591
    if (!replace.empty()) {
243
      if (pos > last_pos) {
244
        ret += str.substr(last_pos, pos - last_pos);
245
      }
246
      last_pos = pos + 1;
247
      ret += replace;
248
    }
249
65591
  }
250
  // Append any remaining symbols.
251
4254
  if (last_pos < str.size()) {
252
4244
    ret += str.substr(last_pos, pos - last_pos);
253
  }
254
140382
  return ret;
255
}
256
257

12876
}  // namespace report