UNPKG

chrome-devtools-frontend

Version:
369 lines (343 loc) • 13.7 kB
// Copyright 2024 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Lantern from '../lantern.js'; const {TCPConnection} = Lantern.Simulation; describe('TCPConnection', () => { describe('#constructor', () => { it('should create the connection', () => { const rtt = 150; const throughput = 1600 * 1024; const connection = new TCPConnection(rtt, throughput); assert.isOk(connection); assert.strictEqual(connection.rtt, rtt); }); }); describe('#maximumSaturatedConnections', () => { it('should compute number of supported simulated requests', () => { const availableThroughput = 1460 * 8 * 10; // 10 TCP segments/second assert.strictEqual(TCPConnection.maximumSaturatedConnections(100, availableThroughput), 1); assert.strictEqual(TCPConnection.maximumSaturatedConnections(300, availableThroughput), 3); assert.strictEqual(TCPConnection.maximumSaturatedConnections(1000, availableThroughput), 10); }); }); describe('.setWarmed', () => { it('adjusts the time to download appropriately', () => { const connection = new TCPConnection(100, Infinity); assert.strictEqual(connection.simulateDownloadUntil(0).timeElapsed, 300); connection.setWarmed(true); assert.strictEqual(connection.simulateDownloadUntil(0).timeElapsed, 100); }); }); describe('.setCongestionWindow', () => { it('adjusts the time to download appropriately', () => { const connection = new TCPConnection(100, Infinity); assert.deepEqual(connection.simulateDownloadUntil(50000), { bytesDownloaded: 50000, extraBytesDownloaded: 0, congestionWindow: 40, roundTrips: 5, timeElapsed: 500, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); connection.setCongestionWindow(40); // will download all in one round trip assert.deepEqual(connection.simulateDownloadUntil(50000), { bytesDownloaded: 50000, extraBytesDownloaded: 0, congestionWindow: 40, roundTrips: 3, timeElapsed: 300, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); }); }); describe('.setH2OverflowBytesDownloaded', () => { it('adjusts the time to download appropriately for H2 connections', () => { const connection = new TCPConnection(100, Infinity, 0, true, true); connection.setWarmed(true); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 200); connection.setH2OverflowBytesDownloaded(20000); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 100); connection.setH2OverflowBytesDownloaded(50000); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 0); }); it('does not adjust the time to download for non-H2 connections', () => { const connection = new TCPConnection(100, Infinity, 0, true, false); connection.setWarmed(true); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 200); connection.setH2OverflowBytesDownloaded(20000); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 200); connection.setH2OverflowBytesDownloaded(50000); assert.strictEqual(connection.simulateDownloadUntil(30000).timeElapsed, 200); }); }); describe('.simulateDownloadUntil', () => { describe('when maximumTime is not set', () => { it('should provide the correct values small payload non-SSL', () => { const connection = new TCPConnection(100, Infinity, 0, false); assert.deepEqual(connection.simulateDownloadUntil(7300), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 2, timeElapsed: 200, connectionTiming: { connectionTime: 150, dnsResolutionTime: 0, sslTime: undefined, // non-SSL timeToFirstByte: 200, }, }); }); it('should provide the correct values small payload SSL', () => { const connection = new TCPConnection(100, Infinity, 0, true); assert.deepEqual(connection.simulateDownloadUntil(7300), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 3, timeElapsed: 300, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); }); it('should provide the correct values small payload H2', () => { const connection = new TCPConnection(100, Infinity, 0, true, true); assert.deepEqual(connection.simulateDownloadUntil(7300), { bytesDownloaded: 7300, extraBytesDownloaded: 7300, congestionWindow: 10, roundTrips: 3, timeElapsed: 300, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); }); it('should provide the correct values response time', () => { const responseTime = 78; const connection = new TCPConnection(100, Infinity, responseTime, true); assert.deepEqual(connection.simulateDownloadUntil(7300), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 3, timeElapsed: 300 + responseTime, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 378, }, }); }); it('should provide the correct values large payload', () => { const connection = new TCPConnection(100, 8 * 1000 * 1000); const bytesToDownload = 10 * 1000 * 1000; // 10 mb assert.deepEqual(connection.simulateDownloadUntil(bytesToDownload), { bytesDownloaded: bytesToDownload, extraBytesDownloaded: 0, congestionWindow: 68, roundTrips: 105, timeElapsed: 10500, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); }); it('should provide the correct values resumed small payload', () => { const connection = new TCPConnection(100, Infinity, 0, true); assert.deepEqual(connection.simulateDownloadUntil(7300, {timeAlreadyElapsed: 250}), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 3, timeElapsed: 50, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }); }); it('should provide the correct values resumed small payload H2', () => { const connection = new TCPConnection(100, Infinity, 0, true, true); connection.setWarmed(true); connection.setH2OverflowBytesDownloaded(10000); assert.deepEqual(connection.simulateDownloadUntil(7300), { bytesDownloaded: 0, extraBytesDownloaded: 2700, // 10000 - 7300 congestionWindow: 10, roundTrips: 0, timeElapsed: 0, connectionTiming: { timeToFirstByte: 0, }, }); }); it('should provide the correct values resumed large payload', () => { const connection = new TCPConnection(100, 8 * 1000 * 1000); const bytesToDownload = 5 * 1000 * 1000; // 5 mb connection.setCongestionWindow(68); assert.deepEqual( connection.simulateDownloadUntil(bytesToDownload, {timeAlreadyElapsed: 5234}), { bytesDownloaded: bytesToDownload, extraBytesDownloaded: 0, congestionWindow: 68, roundTrips: 51, // 5 mb / (1460 * 68) timeElapsed: 5100, connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }, ); }); }); describe('when maximumTime is set', () => { it('should provide the correct values less than TTFB', () => { const connection = new TCPConnection(100, Infinity, 0, false); assert.deepEqual( connection.simulateDownloadUntil(7300, {timeAlreadyElapsed: 0, maximumTimeToElapse: 68}), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 2, timeElapsed: 200, connectionTiming: { connectionTime: 150, dnsResolutionTime: 0, sslTime: undefined, // non-SSL timeToFirstByte: 200, }, }, ); }); it('should provide the correct values just over TTFB', () => { const connection = new TCPConnection(100, Infinity, 0, false); assert.deepEqual( connection.simulateDownloadUntil(7300, {timeAlreadyElapsed: 0, maximumTimeToElapse: 250}), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 2, timeElapsed: 200, connectionTiming: { connectionTime: 150, dnsResolutionTime: 0, sslTime: undefined, // non-SSL timeToFirstByte: 200, }, }, ); }); it('should provide the correct values with already elapsed', () => { const connection = new TCPConnection(100, Infinity, 0, false); assert.deepEqual( connection.simulateDownloadUntil(7300, { timeAlreadyElapsed: 75, maximumTimeToElapse: 250, }), { bytesDownloaded: 7300, extraBytesDownloaded: 0, congestionWindow: 10, roundTrips: 2, timeElapsed: 125, connectionTiming: { connectionTime: 150, dnsResolutionTime: 0, sslTime: undefined, // non-SSL timeToFirstByte: 200, }, }, ); }); it('should provide the correct values large payloads', () => { const connection = new TCPConnection(100, 8 * 1000 * 1000); const bytesToDownload = 10 * 1000 * 1000; // 10 mb assert.deepEqual( connection.simulateDownloadUntil(bytesToDownload, { timeAlreadyElapsed: 500, maximumTimeToElapse: 740, }), { bytesDownloaded: 683280, // should be less than 68 * 1460 * 8 extraBytesDownloaded: 0, congestionWindow: 68, roundTrips: 8, timeElapsed: 800, // skips the handshake because time already elapsed connectionTiming: { connectionTime: 250, dnsResolutionTime: 0, sslTime: 100, timeToFirstByte: 300, }, }, ); }); it('should all add up', () => { const connection = new TCPConnection(100, 8 * 1000 * 1000); const bytesToDownload = 10 * 1000 * 1000; // 10 mb const firstStoppingPoint = 5234; const secondStoppingPoint = 315; const thirdStoppingPoint = 10500 - firstStoppingPoint - secondStoppingPoint; const firstSegment = connection.simulateDownloadUntil(bytesToDownload, { timeAlreadyElapsed: 0, maximumTimeToElapse: firstStoppingPoint, }); const firstOvershoot = firstSegment.timeElapsed - firstStoppingPoint; connection.setCongestionWindow(firstSegment.congestionWindow); const secondSegment = connection.simulateDownloadUntil( bytesToDownload - firstSegment.bytesDownloaded, { timeAlreadyElapsed: firstSegment.timeElapsed, maximumTimeToElapse: secondStoppingPoint - firstOvershoot, }, ); const secondOvershoot = firstOvershoot + secondSegment.timeElapsed - secondStoppingPoint; connection.setCongestionWindow(secondSegment.congestionWindow); const thirdSegment = connection.simulateDownloadUntil( bytesToDownload - firstSegment.bytesDownloaded - secondSegment.bytesDownloaded, {timeAlreadyElapsed: firstSegment.timeElapsed + secondSegment.timeElapsed}, ); const thirdOvershoot = secondOvershoot + thirdSegment.timeElapsed - thirdStoppingPoint; assert.strictEqual(thirdOvershoot, 0); assert.strictEqual( firstSegment.bytesDownloaded + secondSegment.bytesDownloaded + thirdSegment.bytesDownloaded, bytesToDownload, ); assert.strictEqual( firstSegment.timeElapsed + secondSegment.timeElapsed + thirdSegment.timeElapsed, 10500, ); }); }); }); });