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: 118 141 83.7 %
Date: 2019-02-23 22:23:05 Branches: 56 86 65.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 libuv socket information.
11
4
static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
12
  struct sockaddr_storage addr_storage;
13
4
  struct sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage);
14
4
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
15
4
  int addr_size = sizeof(addr_storage);
16
4
  int rc = -1;
17
4
  bool wrote_local_endpoint = false;
18
4
  bool wrote_remote_endpoint = false;
19
20
4
  switch (h->type) {
21
    case UV_UDP:
22
1
      rc = uv_udp_getsockname(&handle->udp, addr, &addr_size);
23
1
      break;
24
    case UV_TCP:
25
3
      rc = uv_tcp_getsockname(&handle->tcp, addr, &addr_size);
26
3
      break;
27
    default:
28
      break;
29
  }
30
4
  if (rc == 0) {
31
    // uv_getnameinfo will format host and port and handle IPv4/IPv6.
32
    uv_getnameinfo_t local;
33
4
    rc = uv_getnameinfo(h->loop, &local, nullptr, addr, NI_NUMERICSERV);
34
35
4
    if (rc == 0) {
36
4
      writer->json_objectstart("localEndpoint");
37
4
      writer->json_keyvalue("host", local.host);
38
4
      writer->json_keyvalue("port", local.service);
39
4
      writer->json_objectend();
40
4
      wrote_local_endpoint = true;
41
    }
42
  }
43
4
  if (!wrote_local_endpoint) writer->json_keyvalue("localEndpoint", null);
44
45
4
  if (h->type == UV_TCP) {
46
    // Get the remote end of the connection.
47
3
    rc = uv_tcp_getpeername(&handle->tcp, addr, &addr_size);
48
3
    if (rc == 0) {
49
      uv_getnameinfo_t remote;
50
2
      rc = uv_getnameinfo(h->loop, &remote, nullptr, addr, NI_NUMERICSERV);
51
52
2
      if (rc == 0) {
53
2
        writer->json_objectstart("remoteEndpoint");
54
2
        writer->json_keyvalue("host", remote.host);
55
2
        writer->json_keyvalue("port", remote.service);
56
2
        writer->json_objectend();
57
2
        wrote_local_endpoint = true;
58
      }
59
    }
60
  }
61
4
  if (!wrote_remote_endpoint) writer->json_keyvalue("remoteEndpoint", null);
62
4
}
63
64
// Utility function to format libuv path information.
65
2
static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
66
2
  MallocedBuffer<char> buffer(0);
67
2
  int rc = -1;
68
2
  size_t size = 0;
69
2
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
70
2
  bool wrote_filename = false;
71
  // First call to get required buffer size.
72
2
  switch (h->type) {
73
    case UV_FS_EVENT:
74
1
      rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
75
1
      break;
76
    case UV_FS_POLL:
77
1
      rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
78
1
      break;
79
    default:
80
      break;
81
  }
82
2
  if (rc == UV_ENOBUFS) {
83
2
    buffer = MallocedBuffer<char>(size + 1);
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 == 0) {
95
      // buffer is not null terminated.
96
2
      buffer.data[size] = '\0';
97
2
      writer->json_keyvalue("filename", buffer.data);
98
2
      wrote_filename = true;
99
    }
100
  }
101
2
  if (!wrote_filename) writer->json_keyvalue("filename", null);
102
2
}
103
104
// Utility function to walk libuv handles.
105
67
void WalkHandle(uv_handle_t* h, void* arg) {
106
67
  const char* type = uv_handle_type_name(h->type);
107
67
  JSONWriter* writer = static_cast<JSONWriter*>(arg);
108
67
  uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
109
110
67
  writer->json_start();
111
112

67
  switch (h->type) {
113
    case UV_FS_EVENT:
114
    case UV_FS_POLL:
115
2
      ReportPath(h, writer);
116
2
      break;
117
    case UV_PROCESS:
118
1
      writer->json_keyvalue("pid", handle->process.pid);
119
1
      break;
120
    case UV_TCP:
121
    case UV_UDP:
122
4
      ReportEndpoints(h, writer);
123
4
      break;
124
    case UV_TIMER: {
125
8
      uint64_t due = handle->timer.timeout;
126
8
      uint64_t now = uv_now(handle->timer.loop);
127
8
      writer->json_keyvalue("repeat", uv_timer_get_repeat(&handle->timer));
128
      writer->json_keyvalue("firesInMsFromNow",
129
8
                            static_cast<int64_t>(due - now));
130
8
      writer->json_keyvalue("expired", now >= due);
131
8
      break;
132
    }
133
    case UV_TTY: {
134
      int height, width, rc;
135
      rc = uv_tty_get_winsize(&(handle->tty), &width, &height);
136
      if (rc == 0) {
137
        writer->json_keyvalue("width", width);
138
        writer->json_keyvalue("height", height);
139
      }
140
      break;
141
    }
142
    case UV_SIGNAL:
143
      // SIGWINCH is used by libuv so always appears.
144
      // See http://docs.libuv.org/en/v1.x/signal.html
145
      writer->json_keyvalue("signum", handle->signal.signum);
146
      writer->json_keyvalue("signal",
147
                            node::signo_string(handle->signal.signum));
148
      break;
149
    default:
150
52
      break;
151
  }
152
153

67
  if (h->type == UV_TCP || h->type == UV_UDP
154
#ifndef _WIN32
155
63
      || h->type == UV_NAMED_PIPE
156
#endif
157
  ) {
158
    // These *must* be 0 or libuv will set the buffer sizes to the non-zero
159
    // values they contain.
160
8
    int send_size = 0;
161
8
    int recv_size = 0;
162
8
    uv_send_buffer_size(h, &send_size);
163
8
    uv_recv_buffer_size(h, &recv_size);
164
8
    writer->json_keyvalue("sendBufferSize", send_size);
165
8
    writer->json_keyvalue("recvBufferSize", recv_size);
166
  }
167
168
#ifndef _WIN32
169


127
  if (h->type == UV_TCP || h->type == UV_NAMED_PIPE || h->type == UV_TTY ||
170
119
      h->type == UV_UDP || h->type == UV_POLL) {
171
    uv_os_fd_t fd_v;
172
8
    int rc = uv_fileno(h, &fd_v);
173
174
8
    if (rc == 0) {
175
8
      writer->json_keyvalue("fd", static_cast<int>(fd_v));
176

8
      switch (fd_v) {
177
        case 0:
178
          writer->json_keyvalue("stdio", "stdin");
179
          break;
180
        case 1:
181
          writer->json_keyvalue("stdio", "stdout");
182
          break;
183
        case 2:
184
          writer->json_keyvalue("stdio", "stderr");
185
          break;
186
      }
187
    }
188
  }
189
#endif
190
191

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

12864
}  // namespace report