diff --git a/src.ts/agent/debuglet.ts b/src.ts/agent/debuglet.ts index 7d7d2d70..762b8281 100644 --- a/src.ts/agent/debuglet.ts +++ b/src.ts/agent/debuglet.ts @@ -533,7 +533,13 @@ export class Debuglet extends EventEmitter { that.logger_.info( '\t' + (response as http.ServerResponse).statusCode + ' completed.'); - if (body.wait_expired) { + if (!body) { + that.logger_.error('\tinvalid list response: empty body'); + that.scheduleBreakpointFetch_( + that.config_.breakpointUpdateIntervalSec); + return; + } + if (body.waitExpired) { that.logger_.info('\tLong poll completed.'); that.scheduleBreakpointFetch_(0 /*immediately*/); return; diff --git a/src.ts/controller.ts b/src.ts/controller.ts index a0a2382a..dd38be0c 100644 --- a/src.ts/controller.ts +++ b/src.ts/controller.ts @@ -27,7 +27,7 @@ import * as qs from 'querystring'; import {Debug} from './debug'; import {Debuggee} from './debuggee'; -import {Breakpoint} from './types/api-types'; +import {Breakpoint, ListBreakpointsQuery, ListBreakpointsResponse} from './types/api-types'; /** @const {string} Cloud Debug API endpoint */ const API = 'https://clouddebugger.googleapis.com/v2/controller'; @@ -85,11 +85,12 @@ export class Controller extends common.ServiceObject { */ listBreakpoints( debuggee: Debuggee, - callback: (err: Error|null, response?: http.ServerResponse, body?: any) => - void): void { + callback: + (err: Error|null, response?: http.ServerResponse, + body?: ListBreakpointsResponse) => void): void { const that = this; assert(debuggee.id, 'should have a registered debuggee'); - const query: any = {success_on_timeout: true}; + const query: ListBreakpointsQuery = {successOnTimeout: true}; if (that.nextWaitToken_) { query.waitToken = that.nextWaitToken_; } diff --git a/src.ts/types/api-types.ts b/src.ts/types/api-types.ts index 2c039d7e..37d3c18a 100644 --- a/src.ts/types/api-types.ts +++ b/src.ts/types/api-types.ts @@ -103,3 +103,14 @@ export interface Breakpoint { [key: string]: string, }; } + +export interface ListBreakpointsQuery { + waitToken?: string; + successOnTimeout?: boolean; +} + +export interface ListBreakpointsResponse { + breakpoints: Breakpoint[]; + nextWaitToken: string; + waitExpired: boolean; +} diff --git a/system-test/test-e2e.js b/system-test/test-e2e.js index 4185378a..81e353ee 100644 --- a/system-test/test-e2e.js +++ b/system-test/test-e2e.js @@ -129,7 +129,7 @@ describe('@google-cloud/debug end-to-end behavior', function () { }); it('should set breakpoints correctly', function() { - this.timeout(25 * 1000); + this.timeout(90 * 1000); // Kick off promise chain by getting a list of debuggees return api.listDebuggees(projectId).then(function(results) { // Check that the debuggee created in this test is among the list of @@ -188,7 +188,7 @@ describe('@google-cloud/debug end-to-end behavior', function () { console.log('-- waiting before checking if the log was written'); return Promise.all([breakpoint, delay(10 * 1000)]); }).then(function(results) { - // Check the contents of the log, and then delete the breakpoint + // Check the contents of the log, but keep the original breakpoint. var breakpoint = results[0]; @@ -197,13 +197,13 @@ describe('@google-cloud/debug end-to-end behavior', function () { 'transcript in child ' + index + ' should contain value of o: ' + child.transcript); }); - return api.deleteBreakpoint(debuggeeId, breakpoint.id); + return Promise.resolve(); }).then(function() { // Set another breakpoint at the same location console.log('-- setting a breakpoint'); return api.setBreakpoint(debuggeeId, { - id: 'breakpoint-1', + id: 'breakpoint-2', location: {path: FILENAME, line: 5}, expressions: ['process'], // Process for large variable condition: 'n === 10' @@ -254,12 +254,24 @@ describe('@google-cloud/debug end-to-end behavior', function () { assert.strictEqual(arg.value, '10'); console.log('-- checking log point was hit again'); children.forEach(function(child) { - assert.ok(child.transcript - .split('LOGPOINT: o is: {"a":[1,"hi",true]}').length > 4); + const count = (child.transcript + .match(/LOGPOINT: o is: \{"a":\[1,"hi",true\]\}/g) || []).length; + assert.ok(count > 4); }); return api.deleteBreakpoint(debuggeeId, breakpoint.id); }).then(function() { + // wait for 60 seconds + console.log('-- waiting for 60 seconds'); + return delay(60 * 1000); + }).then(function() { + // Make sure the log point is continuing to be hit. + console.log('-- checking log point was hit again'); + children.forEach(function(child) { + const count = (child.transcript + .match(/LOGPOINT: o is: \{"a":\[1,"hi",true\]\}/g) || []).length; + assert.ok(count > 60); + }); console.log('-- test passed'); return Promise.resolve(); }); @@ -305,7 +317,7 @@ describe('@google-cloud/debug end-to-end behavior', function () { console.log('-- setting a logpoint'); return api.setBreakpoint(debuggeeId, { - id: 'breakpoint-1', + id: 'breakpoint-3', location: {path: FILENAME, line: 5}, condition: 'n === 10', action: 'LOG', @@ -332,8 +344,8 @@ describe('@google-cloud/debug end-to-end behavior', function () { // If no throttling occurs, we expect ~20 logs since we are logging // 2x per second over a 10 second period. children.forEach(function(child) { - var logCount = child.transcript - .split('LOGPOINT: o is: {"a":[1,"hi",true]}').length - 1; + const logCount = (child.transcript + .match(/LOGPOINT: o is: \{"a":\[1,"hi",true\]\}/g) || []).length; // A log count of greater than 10 indicates that we did not successfully // pause when the rate of `maxLogsPerSecond` was reached. assert(logCount <= 10, 'log count is greater than 10: ' + logCount); diff --git a/test/test-controller.js b/test/test-controller.js index 811e970e..59e7b8ff 100644 --- a/test/test-controller.js +++ b/test/test-controller.js @@ -106,7 +106,7 @@ describe('Controller API', function() { it('should deal with a missing breakpoints response', function(done) { var scope = nock(url) - .get(api + '/debuggees/fake-debuggee/breakpoints?success_on_timeout=true') + .get(api + '/debuggees/fake-debuggee/breakpoints?successOnTimeout=true') .reply(200, { kind: 'whatever' }); var debuggee = { id: 'fake-debuggee' }; @@ -124,7 +124,7 @@ describe('Controller API', function() { tests.forEach(function(invalidResponse, index) { it('should pass test ' + index, function(done) { var scope = nock(url) - .get(api + '/debuggees/fake-debuggee/breakpoints?success_on_timeout=true') + .get(api + '/debuggees/fake-debuggee/breakpoints?successOnTimeout=true') .reply(200, invalidResponse); var debuggee = { id: 'fake-debuggee' }; var controller = new Controller(fakeDebug); @@ -140,7 +140,7 @@ describe('Controller API', function() { it('should throw error on http errors', function(done) { var scope = nock(url) - .get(api + '/debuggees/fake-debuggee/breakpoints?success_on_timeout=true') + .get(api + '/debuggees/fake-debuggee/breakpoints?successOnTimeout=true') .reply(403); var debuggee = { id: 'fake-debuggee' }; var controller = new Controller(fakeDebug); @@ -154,15 +154,15 @@ describe('Controller API', function() { it('should work with waitTokens', function(done) { var scope = nock(url) - .get(api + '/debuggees/fake-debuggee/breakpoints?success_on_timeout=true') + .get(api + '/debuggees/fake-debuggee/breakpoints?successOnTimeout=true') .reply(200, { - wait_expired: true + waitExpired: true }); var debuggee = { id: 'fake-debuggee' }; var controller = new Controller(fakeDebug); controller.listBreakpoints(debuggee, function(err, response, result) { assert.ifError(err, 'not expecting an error'); - assert(response.body.wait_expired, 'should have expired set'); + assert(response.body.waitExpired, 'should have expired set'); scope.done(); done(); }); @@ -176,7 +176,7 @@ describe('Controller API', function() { testsBreakpoints.forEach(function(breakpoints, index) { it('should pass test ' + index, function(done) { var scope = nock(url) - .get(api + '/debuggees/fake-debuggee/breakpoints?success_on_timeout=true') + .get(api + '/debuggees/fake-debuggee/breakpoints?successOnTimeout=true') .reply(200, { breakpoints: breakpoints }); diff --git a/test/test-debuglet.js b/test/test-debuglet.js index 6cc73cc2..8a4a8ef9 100644 --- a/test/test-debuglet.js +++ b/test/test-debuglet.js @@ -498,7 +498,7 @@ describe('Debuglet', function() { var scope = nock(API) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(404) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}); @@ -525,7 +525,7 @@ describe('Debuglet', function() { var scope = nock(API) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, {breakpoints: [bp]}); debuglet.once('registered', function reg(id) { @@ -552,7 +552,7 @@ describe('Debuglet', function() { var scope = nock(API) .post(REGISTER_PATH) .reply(200, { debuggee: { id: DEBUGGEE_ID } }) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, { breakpoints: [{ id: 'test', @@ -590,7 +590,7 @@ describe('Debuglet', function() { var scope = nock(API) .post(REGISTER_PATH) .reply(200, { debuggee: { id: DEBUGGEE_ID } }) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, { breakpoints: [{ id: 'test', @@ -629,11 +629,11 @@ describe('Debuglet', function() { .reply(200, {debuggee: {id: DEBUGGEE_ID}}) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(404) - .get(BPS_PATH + '?success_on_timeout=true') - .reply(200, {wait_expired: true}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') + .reply(200, {waitExpired: true}) + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, {breakpoints: [bp, errorBp]}) .put(BPS_PATH + '/' + errorBp.id, function(body) { @@ -669,7 +669,7 @@ describe('Debuglet', function() { nock(API) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, {breakpoints: [bp]}) .put(BPS_PATH + '/test', function(body) { @@ -717,7 +717,7 @@ describe('Debuglet', function() { nock(API) .post(REGISTER_PATH) .reply(200, {debuggee: {id: DEBUGGEE_ID}}) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .reply(200, {breakpoints: [bp]}) .put(BPS_PATH + '/test', function(body) { @@ -725,7 +725,7 @@ describe('Debuglet', function() { 'The snapshot has expired'; }) .reply(200) - .get(BPS_PATH + '?success_on_timeout=true') + .get(BPS_PATH + '?successOnTimeout=true') .times(4) .reply(200, {breakpoints: [bp]});