diff --git a/src/parser/clonePingResponse.ts b/src/parser/clonePingResponse.ts new file mode 100644 index 0000000..23c2b91 --- /dev/null +++ b/src/parser/clonePingResponse.ts @@ -0,0 +1,20 @@ +import { pingResponse } from "../types"; + +function clonePingResponse(obj: pingResponse): pingResponse { + return { + host: obj.host, + numericHost: obj.numericHost, + alive: obj.alive, + output: obj.output, + time: obj.time, + times: obj.times?.length ? [...obj.times] : [], + min: obj.min, + max: obj.max, + avg: obj.avg, + bufferSize: obj.bufferSize, + stddev: obj.stddev, + packetLoss: obj.packetLoss, + }; +} + +export default clonePingResponse; diff --git a/src/parser/parserFactory.ts b/src/parser/parserFactory.ts index 6007ab1..7453e58 100644 --- a/src/parser/parserFactory.ts +++ b/src/parser/parserFactory.ts @@ -6,21 +6,23 @@ import linux from './linux' import { extendedPingOptions, pingResponse } from '../types' import { ERROR_MESSAGES } from '../messages' import parser from "./parser.interface"; +import clonePingResponse from './clonePingResponse' //create instance of parser based on operating system function parserFactory(platform: string, output?: string[], options?: extendedPingOptions): pingResponse { let parser: parser; let isWindows: boolean = false; + const baseReponse = clonePingResponse(defaultResponse) if (!isPlatformSupported(platform)) { throw new supportedError(ERROR_MESSAGES.PLATFORM_NOT_SUPPORTED.replace('platform', platform)); } if (platform === 'win32') { - parser = new windows(defaultResponse, options); + parser = new windows(baseReponse, options); isWindows = true; } else if (platform === 'darwin') { - parser = new mac(defaultResponse, options); + parser = new mac(baseReponse, options); } else { - parser = new linux(defaultResponse, options); + parser = new linux(baseReponse, options); } let result = parseOutput(parser, isWindows, output); return result; diff --git a/test/parser/clonePingRespons.ts b/test/parser/clonePingRespons.ts new file mode 100644 index 0000000..4933c57 --- /dev/null +++ b/test/parser/clonePingRespons.ts @@ -0,0 +1,51 @@ +import test from "ava"; +import clonePingResponse from "../../src/parser/clonePingResponse"; +import { pingResponse } from "../../src/types"; + +test("clonePingResponse creates a deep copy of pingResponse", (t) => { + const original: pingResponse = { + host: "localhost", + numericHost: "127.0.0.1", + alive: true, + output: "Ping successful", + time: 10, + times: [10, 12, 11], + min: 10, + max: 12, + avg: 11, + bufferSize: 32, + stddev: 1, + packetLoss: "0%", + }; + + const clone = clonePingResponse(original); + + t.deepEqual(clone, original); + t.not(clone, original); + t.not(clone.times, original.times); + + clone.times.push(99); + t.notDeepEqual(clone.times, original.times); +}); + +test("clonePingResponse handles undefined times array", (t) => { + const original: pingResponse = { + host: "localhost", + numericHost: "127.0.0.1", + alive: true, + output: "Ping successful", + time: 10, + times: [], + min: 10, + max: 12, + avg: 11, + bufferSize: 32, + stddev: 1, + packetLoss: "0%", + }; + + const clone = clonePingResponse(original); + console.log({ clone }); + + t.deepEqual(clone.times, []); +}); diff --git a/test/parser/parser.ts b/test/parser/parser.ts index 923907a..b8b0658 100644 --- a/test/parser/parser.ts +++ b/test/parser/parser.ts @@ -1,55 +1,59 @@ -import test from 'ava' -import parserFactory from '../../src/parser/parserFactory' -const fs = require('fs'); -const readline = require('readline'); -import * as response from './replies.json' - +import test from "ava"; +import parserFactory from "../../src/parser/parserFactory"; +const fs = require("fs"); +const readline = require("readline"); +import * as response from "./replies.json"; + +const normalize = (val: any) => ({ + ...val, + bufferSize: val.bufferSize ?? undefined, +}); //function to read file line by line to mock actual response async function processLineByLine(path: string): Promise { - let text: string[] = []; - const fileStream = fs.createReadStream(path); - - //reading file line by line - const rl = readline.createInterface({ - input: fileStream, - output: process.stdout, - console: false - }); - for await (const line of rl) { - // Each line in file will be successively available here as `line`. - text.push(line + '\n'); - } - return text; + let text: string[] = []; + const fileStream = fs.createReadStream(path); + + //reading file line by line + const rl = readline.createInterface({ + input: fileStream, + output: process.stdout, + console: false, + }); + for await (const line of rl) { + // Each line in file will be successively available here as `line`. + text.push(line + "\n"); + } + return text; } -test('ouput for windows IPV4 ping', async t => { - let input = await processLineByLine(__dirname + '/samples/windowsIPV4.txt'); - let output = parserFactory("win32", input); - t.deepEqual(output as any, response.windows_ipv4); -}) - -test('ouput for windows IPV6 ping', async t => { - let input = await processLineByLine(__dirname + '/samples/windowsIPV6.txt'); - let output = parserFactory("win32", input, {IPV6:true}); - t.deepEqual(output as any, response.windows_ipv6); -}) - -test('ouput for linux IPV4 ping', async t => { - let input = await processLineByLine(__dirname + '/samples/linuxIPV4.txt'); - let output = parserFactory("linux", input); - t.deepEqual(output as any, response.linux_ipv4); -}) - -test('ouput for linux IPV6 ping', async t => { - let input = await processLineByLine(__dirname + '/samples/linuxIPV6.txt'); - let output = parserFactory("linux", input, {IPV6:true}); - t.deepEqual(output as any, response.linux_ipv6); -}) - -test('ouput for mac IPV4 ping', async t => { - let input = await processLineByLine(__dirname + '/samples/macIPV4.txt'); - let output = parserFactory("darwin", input); - t.deepEqual(output as any, response.macos_ipv4); -}) - -//TO-DO - Add a mac ipv6 test \ No newline at end of file +test("ouput for windows IPV4 ping", async (t) => { + let input = await processLineByLine(__dirname + "/samples/windowsIPV4.txt"); + let output = parserFactory("win32", input); + t.deepEqual(output as any, response.windows_ipv4); +}); + +test("ouput for windows IPV6 ping", async (t) => { + let input = await processLineByLine(__dirname + "/samples/windowsIPV6.txt"); + let output = parserFactory("win32", input, { IPV6: true }); + t.deepEqual(output, normalize(response.windows_ipv6)); +}); + +test("ouput for linux IPV4 ping", async (t) => { + let input = await processLineByLine(__dirname + "/samples/linuxIPV4.txt"); + let output = parserFactory("linux", input); + t.deepEqual(output as any, normalize(response.linux_ipv4)); +}); + +test("ouput for linux IPV6 ping", async (t) => { + let input = await processLineByLine(__dirname + "/samples/linuxIPV6.txt"); + let output = parserFactory("linux", input, { IPV6: true }); + t.deepEqual(output as any, normalize(response.linux_ipv6)); +}); + +test("ouput for mac IPV4 ping", async (t) => { + let input = await processLineByLine(__dirname + "/samples/macIPV4.txt"); + let output = parserFactory("darwin", input); + t.deepEqual(output as any, normalize(response.macos_ipv4)); +}); + +//TO-DO - Add a mac ipv6 test diff --git a/test/parser/replies.json b/test/parser/replies.json index c40311a..6d8c14f 100644 --- a/test/parser/replies.json +++ b/test/parser/replies.json @@ -1,95 +1,72 @@ { - "windows_ipv4": { - "host": "www.some-domain.com", - "numericHost": "127.0.0.1", - "alive": true, - "output": "Pinging www.some-domain.com [127.0.0.1] with 32 bytes of\nReply from 127.0.0.1: bytes=32 time=564ms TTL=237\nReply from 127.0.0.1: bytes=32 time=555ms TTL=237\nReply from 127.0.0.1: bytes=32 time=554ms TTL=237\nReply from 127.0.0.1: bytes=32 time=548ms TTL=237\n\nPing statistics for 127.0.0.1:\n Packets: Sent = 4, Received = 4, Lost = 0 (0% loss)\nApproximate round trip times in milli-seconds:\n Minimum = 548ms, Maximum = 564ms, Average = 555ms\n", - "time": 564, - "times": [ - 564, - 555, - 554, - 548 - ], - "min": "548.000", - "max": "564.000", - "avg": "555.000", - "bufferSize": 32, - "stddev": "5.717", - "packetLoss": "0" - }, - "macos_ipv4": { - "host": "google.com", - "numericHost": "172.217.24.46", - "alive": true, - "output": "PING google.com (172.217.24.46): 56 data bytes\n64 bytes from 172.217.24.46: icmp_seq=0 ttl=54 time=5.371 ms\n64 bytes from 172.217.24.46: icmp_seq=1 ttl=54 time=4.269 ms\n64 bytes from 172.217.24.46: icmp_seq=2 ttl=54 time=4.970 ms\n64 bytes from 172.217.24.46: icmp_seq=3 ttl=54 time=5.228 ms\n\n--- google.com ping statistics ---\n4 packets transmitted, 4 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 4.269/4.960/5.371/0.424 ms\n", - "time": 5.371, - "times": [ - 5.371, - 4.269, - 4.97, - 5.228 - ], - "min": "4.269", - "max": "5.371", - "avg": "4.960", - "bufferSize": 32, - "stddev": "0.424", - "packetLoss": "0.0" - }, - "linux_ipv4": { - "host": "localhost", - "numericHost": "127.0.0.1", - "alive": true, - "output": "PING localhost (127.0.0.1) 56(84) bytes of data.\n64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.022 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.027 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.029 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.030 ms\n\n--- localhost ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 2999ms\nrtt min/avg/max/mdev = 0.022/0.027/0.030/0.003 ms\n", - "time": 0.022, - "times": [ - 0.022, - 0.027, - 0.029, - 0.03 - ], - "min": "0.022", - "max": "0.030", - "avg": "0.027", - "bufferSize": 32, - "stddev": "0.003", - "packetLoss": "0" - }, - "linux_ipv6": { - "host": "2606:4700:4700::1111", - "numericHost": "2606:4700:4700::1111", - "alive": true, - "output": "PING 2606:4700:4700::1111(2606:4700:4700::1111) 56 data bytes\n64 bytes from 2606:4700:4700::1111: icmp_seq=1 ttl=57 time=0.672 ms\n64 bytes from 2606:4700:4700::1111: icmp_seq=2 ttl=57 time=1.00 ms\n\n--- 2606:4700:4700::1111 ping statistics ---\n2 packets transmitted, 2 received, 0% packet loss, time 1000ms\nrtt min/avg/max/mdev = 0.672/0.840/1.009/0.170 ms\n", - "time": 0.672, - "times": [ - 0.672, - 1.00 - ], - "min": "0.672", - "max": "1.009", - "avg": "0.840", - "bufferSize": 32, - "stddev": "0.170", - "packetLoss": "0" - }, - "windows_ipv6": { - "host": "fe80::2940:90ec:a964:4b42%7", - "numericHost": "fe80::2940:90ec:a964:4b42%7", - "alive": true, - "output": "Pinging fe80::2940:90ec:a964:4b42%7 with 32 bytes of data:\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\n\nPing statistics for fe80::2940:90ec:a964:4b42%7:\n Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),\nApproximate round trip times in milli-seconds:\n Minimum = 0ms, Maximum = 0ms, Average = 0ms\n", - "time": 1, - "times": [ - 1, - 1, - 1, - 1 - ], - "min": "0.000", - "max": "0.000", - "avg": "0.000", - "bufferSize": 32, - "stddev": "5.717", - "packetLoss": "0" - } -} \ No newline at end of file + "windows_ipv4": { + "host": "www.some-domain.com", + "numericHost": "127.0.0.1", + "alive": true, + "output": "Pinging www.some-domain.com [127.0.0.1] with 32 bytes of\nReply from 127.0.0.1: bytes=32 time=564ms TTL=237\nReply from 127.0.0.1: bytes=32 time=555ms TTL=237\nReply from 127.0.0.1: bytes=32 time=554ms TTL=237\nReply from 127.0.0.1: bytes=32 time=548ms TTL=237\n\nPing statistics for 127.0.0.1:\n Packets: Sent = 4, Received = 4, Lost = 0 (0% loss)\nApproximate round trip times in milli-seconds:\n Minimum = 548ms, Maximum = 564ms, Average = 555ms\n", + "time": 564, + "times": [564, 555, 554, 548], + "min": "548.000", + "max": "564.000", + "avg": "555.000", + "bufferSize": 32, + "stddev": "5.717", + "packetLoss": "0" + }, + "macos_ipv4": { + "host": "google.com", + "numericHost": "172.217.24.46", + "alive": true, + "output": "PING google.com (172.217.24.46): 56 data bytes\n64 bytes from 172.217.24.46: icmp_seq=0 ttl=54 time=5.371 ms\n64 bytes from 172.217.24.46: icmp_seq=1 ttl=54 time=4.269 ms\n64 bytes from 172.217.24.46: icmp_seq=2 ttl=54 time=4.970 ms\n64 bytes from 172.217.24.46: icmp_seq=3 ttl=54 time=5.228 ms\n\n--- google.com ping statistics ---\n4 packets transmitted, 4 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 4.269/4.960/5.371/0.424 ms\n", + "time": 5.371, + "times": [5.371, 4.269, 4.97, 5.228], + "min": "4.269", + "max": "5.371", + "avg": "4.960", + "bufferSize": null, + "stddev": "0.424", + "packetLoss": "0.0" + }, + "linux_ipv4": { + "host": "localhost", + "numericHost": "127.0.0.1", + "alive": true, + "output": "PING localhost (127.0.0.1) 56(84) bytes of data.\n64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.022 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.027 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.029 ms\n64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.030 ms\n\n--- localhost ping statistics ---\n4 packets transmitted, 4 received, 0% packet loss, time 2999ms\nrtt min/avg/max/mdev = 0.022/0.027/0.030/0.003 ms\n", + "time": 0.022, + "times": [0.022, 0.027, 0.029, 0.03], + "min": "0.022", + "max": "0.030", + "avg": "0.027", + "bufferSize": null, + "stddev": "0.003", + "packetLoss": "0" + }, + "linux_ipv6": { + "host": "2606:4700:4700::1111", + "numericHost": "2606:4700:4700::1111", + "alive": true, + "output": "PING 2606:4700:4700::1111(2606:4700:4700::1111) 56 data bytes\n64 bytes from 2606:4700:4700::1111: icmp_seq=1 ttl=57 time=0.672 ms\n64 bytes from 2606:4700:4700::1111: icmp_seq=2 ttl=57 time=1.00 ms\n\n--- 2606:4700:4700::1111 ping statistics ---\n2 packets transmitted, 2 received, 0% packet loss, time 1000ms\nrtt min/avg/max/mdev = 0.672/0.840/1.009/0.170 ms\n", + "time": 0.672, + "times": [0.672, 1.0], + "min": "0.672", + "max": "1.009", + "avg": "0.840", + "bufferSize": null, + "stddev": "0.170", + "packetLoss": "0" + }, + "windows_ipv6": { + "host": "fe80::2940:90ec:a964:4b42%7", + "numericHost": "fe80::2940:90ec:a964:4b42%7", + "alive": true, + "output": "Pinging fe80::2940:90ec:a964:4b42%7 with 32 bytes of data:\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\nReply from fe80::2940:90ec:a964:4b42%7: time<1ms\n\nPing statistics for fe80::2940:90ec:a964:4b42%7:\n Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),\nApproximate round trip times in milli-seconds:\n Minimum = 0ms, Maximum = 0ms, Average = 0ms\n", + "time": 1, + "times": [1, 1, 1, 1], + "min": "0.000", + "max": "0.000", + "avg": "0.000", + "bufferSize": null, + "stddev": "0.000", + "packetLoss": "0" + } +}