<|start_filename|>test/fixtures/apps/mock-production-app-do-not-force/config/config.js<|end_filename|>
'use strict';

exports.watcher = {
  // watcher 在 prod 中默认没有设置 type，防止框架开发者忘记设置，这里设置一下，避免报错
  type: 'development',
};

exports.logger = {
  level: 'DEBUG',
  allowDebugAtProd: true,
};

exports.keys = 'foo';


<|start_filename|>test/fixtures/apps/dumpconfig-circular/config/config.default.js<|end_filename|>
exports.dynamic = 0;

exports.keys = 'test key';
exports.foo = [];


<|start_filename|>test/fixtures/apps/app-server-timeout/config/config.default.js<|end_filename|>
exports.keys = 'my keys';

exports.serverTimeout = 100;


<|start_filename|>test/fixtures/apps/singleton-demo/create.js<|end_filename|>
'use strict';

class DataService {
  constructor(config) {
    this.config = config;
  }

  async getConfig() {
    return this.config;
  }

  ready(done) {
    setTimeout(done, 1000);
  }
}

let count = 0;

exports.sync = (config, app) => {
  const done = app.readyCallback(`DataService-${count++}`);
  const dataService = new DataService(config);
  dataService.ready(done);
  return dataService;
};

exports.async = async (config, app) => {
  const done = app.readyCallback(`DataService-${count++}`);
  const dataService = new DataService(config);
  dataService.ready(done);
  return dataService;
};


<|start_filename|>test/ts/index.test.js<|end_filename|>
'use strict';

const assert = require('assert');
const request = require('supertest');
const coffee = require('coffee');
const path = require('path');
const utils = require('../utils');

describe('test/ts/index.test.js', () => {
  describe('compiler code', () => {
    let app;
    before(async () => {
      await coffee.fork(
        require.resolve('typescript/bin/tsc'),
        [ '-p', path.resolve(__dirname, '../fixtures/apps/app-ts/tsconfig.json') ]
      )
        .debug()
        .expect('code', 0)
        .end();

      app = utils.app('apps/app-ts');
      await app.ready();
    });

    after(async () => {
      await app.close();
      assert.deepStrictEqual(app._app.stages, [
        'configWillLoad',
        'configDidLoad',
        'didLoad',
        'willReady',
        'didReady',
        'serverDidReady',
        'beforeClose',
      ]);
    });

    it('controller run ok', done => {
      request(app.callback())
        .get('/foo')
        .expect(200)
        .expect({ env: 'unittest' })
        .end(done);
    });

    it('controller of app.router run ok', done => {
      request(app.callback())
        .get('/test')
        .expect(200)
        .expect({ env: 'unittest' })
        .end(done);
    });
  });

  describe('type check', () => {
    it('should compile with esModuleInterop without error', async () => {
      await coffee.fork(
        require.resolve('typescript/bin/tsc'),
        [ '-p', path.resolve(__dirname, '../fixtures/apps/app-ts-esm/tsconfig.json') ]
      )
        .debug()
        .expect('code', 0)
        .end();
    });

    it('should compile type-check ts without error', async () => {
      await coffee.fork(
        require.resolve('typescript/bin/tsc'),
        [ '-p', path.resolve(__dirname, '../fixtures/apps/app-ts-type-check/tsconfig.json') ]
      )
        .debug()
        .expect('code', 0)
        .end();
    });

    it('should throw error with type-check-error ts', async () => {
      await coffee.fork(
        require.resolve('typescript/bin/tsc'),
        [ '-p', path.resolve(__dirname, '../fixtures/apps/app-ts-type-check/tsconfig-error.json') ]
      )
        // .debug()
        .expect('stdout', /Property 'ctx' is protected/)
        .expect('stdout', /Property 'localsCheckAny' does not exist on type 'string'/)
        .expect('stdout', /Property 'configKeysCheckAny' does not exist on type 'string'/)
        .expect('stdout', /Property 'appCheckAny' does not exist on type 'Application'/)
        .expect('stdout', /Property 'serviceLocalCheckAny' does not exist on type 'string'/)
        .expect('stdout', /Property 'serviceConfigCheckAny' does not exist on type 'string'/)
        .expect('stdout', /Property 'serviceAppCheckAny' does not exist on type 'Application'/)
        .expect('stdout', /Property 'checkSingleTon' does not exist/)
        .expect('stdout', /Property 'directory' is missing in type '{}' but required in type 'CustomLoaderConfig'/)
        .notExpect('stdout', /Cannot find module 'yadan'/)
        .expect('stdout', /Object is possibly 'undefined'\./)
        .expect('stdout', /Expected 1 arguments, but got 0\./)
        .expect('stdout', /Expected 0-1 arguments, but got 2\./)
        .expect('code', 2)
        .end();
    });
  });
});


<|start_filename|>test/fixtures/custom-egg/index.js<|end_filename|>
'use strict';

module.exports = require('../../../index');
module.exports.Application = class Application extends module.exports.Application {
  constructor(...args) {
    super(...args);
    this.customEgg = true;
  }

  get [Symbol.for('egg#eggPath')]() {
    return __dirname;
  }
};


<|start_filename|>test/fixtures/apps/dumpconfig-circular/app.js<|end_filename|>
const sleep = require('mz-modules/sleep');

module.exports = app => {
  app.beforeStart(function*() {
    yield sleep(500);
    app.config.foo.push(app.config.foo);
  });
};


<|start_filename|>test/fixtures/apps/custom-loader/app.js<|end_filename|>
'use strict';

module.exports = class {
  constructor(app) {
    this.app = app;
  }

  async didLoad() {
    const ctx = this.app.createAnonymousContext();
    this.app.beforeLoad = await ctx.repository.user.beforeLoad();
  }
};


<|start_filename|>test/fixtures/apps/agent-logger-config/config/config.default.js<|end_filename|>
'use strict';

module.exports = {
  logger: {
    dir: '/tmp/foo',
  },
};


<|start_filename|>test/lib/core/context_httpclient_timeout.test.js<|end_filename|>
'use strict';

const assert = require('assert-extends');
const utils = require('../../utils');

describe('test/lib/core/context_httpclient_timeout.test.js', () => {
  let url;
  let app;

  before(() => {
    app = utils.app('apps/context_httpclient_timeout');
    return app.ready();
  });
  before(async () => {
    url = await utils.startLocalServer();
  });

  it('should request timeout override agent socket timeout', () => {
    app.httpclient.agent.options.timeout = 1000;
    const ctx = app.mockContext();
    return assert.asyncThrows(async () => {
      await ctx.httpclient.request(`${url}/timeout`, { timeout: 1500 });
    }, /ResponseTimeoutError: Response timeout for 1500ms/);
  });
});


<|start_filename|>test/fixtures/apps/demo/index.js<|end_filename|>
const egg = require('../../../../');

egg.start().then(app => {
  app.listen(3000);
  console.log('listen 3000');
});


<|start_filename|>test/fixtures/apps/singleton-demo/config/config.default.js<|end_filename|>
'use strict';

exports.dataService = {
  clients: {
    first: { foo1: 'bar1' },
    second: { foo2: 'bar2' },
  },

  default: {
    foo: 'bar',
  }
};

exports.dataServiceAsync = {
  clients: {
    first: { foo1: 'bar1' },
    second: { foo2: 'bar2' },
  },

  default: {
    foo: 'bar',
  }
};

exports.keys = 'test key';


<|start_filename|>test/app/extend/request.test.js<|end_filename|>
'use strict';

const assert = require('assert');
const mm = require('egg-mock');
const urllib = require('urllib');
const utils = require('../../utils');

describe('test/app/extend/request.test.js', () => {
  describe('normal', () => {
    let app;
    let ctx;
    let req;
    before(() => {
      app = utils.app('apps/demo');
      return app.ready();
    });
    after(() => app.close());
    beforeEach(() => {
      ctx = app.mockContext();
      req = ctx.request;
    });
    afterEach(mm.restore);

    describe('req.host', () => {
      it('should return host with port', () => {
        mm(req.header, 'host', 'foo.com:3000');
        assert(req.hostname === 'foo.com');
      });

      it('should return "" when no host present', () => {
        assert(typeof req.host === 'string');
        assert(req.host === '');
      });

      it('should not allow X-Forwarded-Host header', () => {
        mm(app.config, 'proxy', true);
        mm(req.header, 'x-forwarded-host', 'foo.com');
        mm(req.header, 'host', 'bar.com');
        assert(typeof req.host === 'string');
        assert(req.host === 'bar.com');
      });

      it('should return host from Host header when proxy=false', () => {
        mm(app.config, 'proxy', false);
        mm(req.header, 'x-forwarded-host', 'foo.com');
        mm(req.header, 'host', 'bar.com');
        assert(typeof req.host === 'string');
        assert(req.host === 'bar.com');
      });

      it('should custom hostHeaders', () => {
        mm(app.config, 'proxy', true);
        mm(app.config, 'hostHeaders', 'x-forwarded-host');
        mm(req.header, 'x-forwarded-host', 'foo.com');
        mm(req.header, 'host', 'bar.com');
        assert(typeof req.host === 'string');
        assert(req.host === 'foo.com');
      });
    });

    describe('req.hostname', () => {
      it('should return hostname with port', () => {
        mm(req.header, 'host', 'foo.com:3000');
        assert(req.hostname === 'foo.com');
      });

      it('should return "" when no host present', () => {
        assert(typeof req.hostname === 'string');
        assert(req.hostname === '');
      });
    });

    describe('req.ip', () => {
      it('should return ipv4', () => {
        mm(req.socket, 'remoteAddress', '::ffff:127.0.0.1');
        assert(req.ip === '127.0.0.1');
        assert(req.ip === '127.0.0.1');
      });

      it('should work with proxy', () => {
        mm(req.socket, 'remoteAddress', '::ffff:127.0.0.1');
        mm(req.header, 'x-forwarded-for', '127.0.0.1, 127.0.0.2, 127.0.0.3');
        mm(app.config, 'proxy', true);
        mm(app.config, 'maxProxyCount', 1);
        assert(req.ip === '127.0.0.2');
      });
    });

    describe('req.ips', () => {
      it('should used x-forwarded-for', () => {
        mm(req.header, 'x-forwarded-for', '127.0.0.1,127.0.0.2,127.0.0.3');
        assert.deepEqual(req.ips, [ '127.0.0.1', '127.0.0.2', '127.0.0.3' ]);
      });

      it('should used work with maxProxyCount', () => {
        mm(req.header, 'x-forwarded-for', '127.0.0.1,127.0.0.2,127.0.0.3');
        mm(app.config, 'maxProxyCount', 1);
        assert.deepEqual(req.ips, [ '127.0.0.2', '127.0.0.3' ]);
      });

      it('should used work with maxIpsCount', () => {
        mm(req.header, 'x-forwarded-for', '127.0.0.1,127.0.0.2,127.0.0.3');
        mm(app.config, 'maxIpsCount', 1);
        assert.deepEqual(req.ips, [ '127.0.0.3' ]);
      });

      it('should used x-real-ip', () => {
        mm(app.config, 'ipHeaders', 'X-Forwarded-For, X-Real-IP');
        mm(req.header, 'x-forwarded-for', '');
        mm(req.header, 'x-real-ip', '127.0.0.1,127.0.0.2');
        assert.deepEqual(req.ips, [ '127.0.0.1', '127.0.0.2' ]);
      });

      it('should return []', () => {
        mm(req.header, 'x-forwarded-for', '');
        mm(req.header, 'x-real-ip', '');
        assert.deepEqual(req.ips, []);
      });

      it('should return [] when proxy=false', () => {
        mm(app.config, 'proxy', false);
        mm(req.header, 'x-forwarded-for', '127.0.0.1,127.0.0.2');
        assert.deepEqual(req.ips, []);
      });
    });

    describe('req.protocol', () => {
      it('should return http when it not config and no protocol header', () => {
        mm(app.config, 'protocol', null);
        return app.httpRequest()
          .get('/protocol')
          .expect('http');
      });

      it('should return value of X-Custom-Proto', () => {
        mm(app.config, 'protocolHeaders', 'X-Forwarded-Proto, X-Custom-Proto');
        return app.httpRequest()
          .get('/protocol')
          .set('X-Custom-Proto', 'https')
          .expect('https');
      });

      it('should ignore X-Client-Scheme', () => {
        mm(app.config, 'protocolHeaders', 'X-Forwarded-Proto');
        return app.httpRequest()
          .get('/protocol')
          .set('X-Client-Scheme', 'https')
          .expect('http');
      });

      it('should return value of X-Forwarded-Proto', () => {
        return app.httpRequest()
          .get('/protocol')
          .set('x-forwarded-proto', 'https')
          .expect('https');
      });

      it('should ignore X-Forwarded-Proto when proxy=false', () => {
        mm(app.config, 'proxy', false);
        return app.httpRequest()
          .get('/protocol')
          .set('x-forwarded-proto', 'https')
          .expect('http');
      });

      it('should ignore X-Forwarded-Proto', () => {
        mm(app.config, 'protocolHeaders', '');
        return app.httpRequest()
          .get('/protocol')
          .set('x-forwarded-proto', 'https')
          .expect('http');
      });

      it('should return value from config', () => {
        mm(app.config, 'protocol', 'https');
        return app.httpRequest()
          .get('/protocol')
          .expect('https');
      });

      it('should return value from socket.encrypted', () => {
        const ctx = app.mockContext();
        ctx.request.socket.encrypted = true;
        assert(ctx.request.protocol === 'https');
      });
    });

    describe('this.query && this.queries can be modified', () => {
      it('should success with querystring present', () => {
        req.querystring = 'a=a&b=b1&b=b2';
        assert.deepEqual(req.query, { a: 'a', b: 'b1' });
        assert.deepEqual(req.queries, { a: [ 'a' ], b: [ 'b1', 'b2' ] });
        req.query.a = 'aa';
        req.queries.b = [ 'bb' ];
        assert.deepEqual(req.query, { a: 'aa', b: 'b1' });
        assert.deepEqual(req.queries, { a: [ 'a' ], b: [ 'bb' ] });
      });

      it('should success with empty querystring', () => {
        req.querystring = '';
        assert.deepEqual(req.query, {});
        assert.deepEqual(req.queries, {});
        req.query.a = 'aa';
        req.queries.b = [ 'bb' ];
        assert.deepEqual(req.query, { a: 'aa' });
        assert.deepEqual(req.queries, { b: [ 'bb' ] });
      });
    });

    describe('this.query[key] => String', () => {
      function expectQuery(querystring, query) {
        mm(req, 'querystring', querystring);
        assert.deepEqual(req.query, query);
        mm.restore();
      }

      it('should get string value', () => {
        expectQuery('=b', {});
        expectQuery('a=b', { a: 'b' });
        expectQuery('a=&', { a: '' });
        expectQuery('a=b&', { a: 'b' });
        expectQuery('a.=b', { 'a.': 'b' });
        expectQuery('a=b&a=c', { a: 'b' });
        expectQuery('a=&a=c', { a: '' });
        expectQuery('a=c&a=b', { a: 'c' });
        expectQuery('a=c&a=b&b=bb', { a: 'c', b: 'bb' });
        expectQuery('a[=c&a[=b', { 'a[': 'c' });
        expectQuery('a{=c&a{=b', { 'a{': 'c' });
        expectQuery('a[]=c&a[]=b', { 'a[]': 'c' });
        expectQuery('a[]=&a[]=b', { 'a[]': '' });
        expectQuery('a[foo]=c', { 'a[foo]': 'c' });
        expectQuery('a[foo][bar]=c', { 'a[foo][bar]': 'c' });
        expectQuery('a=', { a: '' });
        expectQuery('a[]=a&a=b&a=c', { 'a[]': 'a', a: 'b' });
      });

      it('should get undefined when key not exists', () => {
        expectQuery('a=b', { a: 'b' });
      });
    });

    describe('this.queries[key] => Array', () => {
      function expectQueries(querystring, query) {
        mm(req, 'querystring', querystring);
        assert.deepEqual(req.queries, query);
        mm.restore();
      }

      it('should get array value', () => {
        expectQueries('', { });
        expectQueries('a=', { a: [ '' ] });
        expectQueries('a=&', { a: [ '' ] });
        expectQueries('a=b&', { a: [ 'b' ] });
        expectQueries('a.=', { 'a.': [ '' ] });
        expectQueries('a=&a=&a=&a=&a=&a=&a=&a=', { a: [ '', '', '', '', '', '', '', '' ] });
        expectQueries('a=&a=&a=&a=&a=&a=&a=&a=&', { a: [ '', '', '', '', '', '', '', '' ] });
        expectQueries('a=&a=&a=&a=&a=&a=&a=&a=&&&&', { a: [ '', '', '', '', '', '', '', '' ] });
        expectQueries('a=b', { a: [ 'b' ] });
        expectQueries('a={}', { a: [ '{}' ] });
        expectQueries('a=[]', { a: [ '[]' ] });
        expectQueries('a[]=[]', { 'a[]': [ '[]' ], a: [ '[]' ] });
        expectQueries('a[]=&a[]=', { 'a[]': [ '', '' ], a: [ '', '' ] });
        expectQueries('a[]=[]&a[]=[]', { 'a[]': [ '[]', '[]' ], a: [ '[]', '[]' ] });
        expectQueries('a=b&a=c', { a: [ 'b', 'c' ] });
        expectQueries('a=&a=c', { a: [ '', 'c' ] });
        expectQueries('a=c&a=b', { a: [ 'c', 'b' ] });
        expectQueries('a=c&a=b&b=bb', { a: [ 'c', 'b' ], b: [ 'bb' ] });
        expectQueries('a[=c&a[=b', { 'a[': [ 'c', 'b' ] });
        expectQueries('a{=c&a{=b', { 'a{': [ 'c', 'b' ] });
        expectQueries('a[]=c&a[]=b', { 'a[]': [ 'c', 'b' ], a: [ 'c', 'b' ] });
        expectQueries('a[]=&a[]=b', { 'a[]': [ '', 'b' ], a: [ '', 'b' ] });
        expectQueries('a[]=&a[]=b&a=foo', { 'a[]': [ '', 'b' ], a: [ 'foo' ] });
        expectQueries('a=bar&a[]=&a[]=b&a=foo', { 'a[]': [ '', 'b' ], a: [ 'bar', 'foo' ] });

        // a[][] 这种不支持自动变化为 a
        expectQueries('a[][]=&a[][]=b', { 'a[][]': [ '', 'b' ] });
        expectQueries('a][]=&a][]=b', { 'a][]': [ '', 'b' ] });
        expectQueries('a[[]=&a[[]=b', { 'a[[]': [ '', 'b' ] });
        expectQueries('[]=&[]=b', { '[]': [ '', 'b' ] });

        // a[], a 混搭的时候，只返回最后一个 a 的值
        expectQueries('a[]=a&a=b&a=c', { 'a[]': [ 'a' ], a: [ 'b', 'c' ] });

        // object
        expectQueries('a[foo]=c', { 'a[foo]': [ 'c' ] });
        expectQueries('a[foo]=c&a=b', { 'a[foo]': [ 'c' ], a: [ 'b' ] });
        expectQueries('a[foo]=c&a=b&b=bb&d=d1&d=d2', {
          'a[foo]': [ 'c' ],
          a: [ 'b' ],
          b: [ 'bb' ],
          d: [ 'd1', 'd2' ],
        });
        expectQueries('a[foo]=c&a[]=b&a[]=d', {
          'a[foo]': [ 'c' ],
          'a[]': [ 'b', 'd' ],
          a: [ 'b', 'd' ],
        });
        expectQueries('a[foo]=c&a[]=b&a[]=d&c=cc&c=c2&c=', {
          'a[foo]': [ 'c' ],
          'a[]': [ 'b', 'd' ],
          a: [ 'b', 'd' ],
          c: [ 'cc', 'c2', '' ],
        });
        expectQueries('a[foo][bar]=c', {
          'a[foo][bar]': [ 'c' ],
        });
      });

      it('should get undefined when key not exists', () => {
        expectQueries('a=b', { a: [ 'b' ] });
      });
    });

    describe('this.query = obj', () => {
      it('should set query with object', () => {
        mm(req, 'querystring', 'a=c');
        assert.deepEqual(req.query, { a: 'c' });
        req.query = {};
        assert.deepEqual(req.query, {});
        assert(req.querystring === '');

        req.query = { foo: 'bar' };
        assert.deepEqual(req.query, { foo: 'bar' });
        assert(req.querystring === 'foo=bar');

        req.query = { array: [ 1, 2 ] };
        assert.deepEqual(req.query, { array: '1' });
        assert(req.querystring === 'array=1&array=2');
      });
    });

    describe('request.acceptJSON', () => {
      it('should true when url path ends with .json', async () => {
        mm(req, 'path', 'hello.json');
        assert(req.acceptJSON === true);
      });

      it('should true when response is json', async () => {
        const context = app.mockContext({
          headers: {
            accept: 'text/html',
          },
          url: '/',
        });
        context.type = 'application/json';
        assert(context.request.acceptJSON === true);
      });

      it('should true when accept json', async () => {
        const context = app.mockContext({
          headers: {
            accept: 'application/json',
          },
          url: '/',
        });
        assert(context.request.acceptJSON === true);
      });

      it('should false when do not accept json', async () => {
        const context = app.mockContext({
          headers: {
            accept: 'text/html',
          },
          url: '/',
        });
        const request = context.request;
        assert(request.acceptJSON === false);
      });
    });
  });

  describe('work with egg app', () => {
    let app;
    let host;
    before(() => {
      app = utils.app('apps/querystring-extended');
      return app.ready();
    });
    before(done => {
      app.listen(0, function() {
        host = `http://127.0.0.1:${this.address().port}`;
        done();
      });
    });
    after(() => app.close());

    it('should return query and queries', done => {
      urllib.request(`${host}/?p=a,b&p=b,c&a[foo]=bar`, {
        dataType: 'json',
      }, (err, body) => {
        assert.deepEqual(body, {
          query: { p: 'a,b', 'a[foo]': 'bar' },
          queries: { p: [ 'a,b', 'b,c' ], 'a[foo]': [ 'bar' ] },
        });
        done(err);
      });
    });

    it('should work with encodeURIComponent', done => {
      urllib.request(`${host}/?p=a,b&p=b,c&${encodeURIComponent('a[foo]')}=bar`, {
        dataType: 'json',
      }, (err, body) => {
        assert.deepEqual(body, {
          query: { p: 'a,b', 'a[foo]': 'bar' },
          queries: { p: [ 'a,b', 'b,c' ], 'a[foo]': [ 'bar' ] },
        });
        done(err);
      });
    });
  });
});


<|start_filename|>test/fixtures/apps/context_httpclient_timeout/config/config.default.js<|end_filename|>
'use strict';

exports.keys = 'test key';

exports.httpclient = {
  httpAgent: {
    timeout: 1000,
  },
};


<|start_filename|>test/fixtures/apps/custom-loader/app/router.js<|end_filename|>
'use strict';

module.exports = app => {
  app.router.get('/users/:name', app.controller.user.get);
  app.router.get('/beforeLoad', app.controller.user.beforeLoad);
};


<|start_filename|>test/fixtures/apps/singleton-demo/agent.js<|end_filename|>
'use strict';

const createDataService = require('./create').sync;
const createDataServiceAsync = require('./create').async;

module.exports = agent => {
  agent.addSingleton('dataService', createDataService);
  agent.addSingleton('dataServiceAsync', createDataServiceAsync);
};


<|start_filename|>lib/core/messenger/index.js<|end_filename|>
'use strict';

const LocalMessenger = require('./local');
const IPCMessenger = require('./ipc');

/**
 * @class Messenger
 */

exports.create = egg => {
  return egg.options.mode === 'single'
    ? new LocalMessenger(egg)
    : new IPCMessenger(egg);
};


<|start_filename|>test/agent.test.js<|end_filename|>
'use strict';

const assert = require('assert');
const mock = require('egg-mock');
const path = require('path');
const utils = require('./utils');

describe('test/agent.test.js', () => {
  afterEach(mock.restore);
  let app;

  before(() => {
    app = utils.app('apps/agent-logger-config');
    return app.ready();
  });
  after(() => app.close());

  it('agent logger config should work', () => {
    const fileTransport = app._agent.logger.get('file');
    assert(fileTransport.options.file === path.join('/tmp/foo', 'egg-agent.log'));
  });
});


<|start_filename|>lib/core/base_hook_class.js<|end_filename|>
'use strict';

const assert = require('assert');
const INSTANCE = Symbol('BaseHookClass#instance');

class BaseHookClass {

  constructor(instance) {
    this[INSTANCE] = instance;
  }

  get logger() {
    return this[INSTANCE].logger;
  }

  get config() {
    return this[INSTANCE].config;
  }

  get app() {
    assert(this[INSTANCE].type === 'application', 'agent boot should not use app instance');
    return this[INSTANCE];
  }

  get agent() {
    assert(this[INSTANCE].type === 'agent', 'app boot should not use agent instance');
    return this[INSTANCE];
  }
}

module.exports = BaseHookClass;


<|start_filename|>test/fixtures/apps/custom-loader/config/config.default.js<|end_filename|>
'use strict';

module.exports = {
  keys: '123',
  customLoader: {
    adapter: {
      directory: 'app/adapter',
      inject: 'app',
    },
    repository: {
      directory: 'app/repository',
      inject: 'ctx',
    },
  },
};


<|start_filename|>test/fixtures/apps/schedule/app/schedule/hello.js<|end_filename|>
'use strict';

module.exports = app => {
  return class LoggerExample extends app.Subscription {
    static get schedule() {
      return {
        type: 'worker',
        cron: '0 0 3 * * *',
        immediate: true,
      };
    }

    async subscribe() {
      this.ctx.logger.info('Info about your task');
    }
  }
};


<|start_filename|>test/fixtures/apps/custom-loader/app/adapter/docker.js<|end_filename|>
'use strict';

class DockerAdapter {
  constructor(app) {
    this.app = app;
  }

  async inspectDocker() {
    return 'docker';
  }

}

module.exports = DockerAdapter;


<|start_filename|>test/fixtures/apps/app-server-timeout/app/router.js<|end_filename|>
'use strict';

const { sleep } = require('mz-modules');

module.exports = app => {
  app.get('/', async ctx => {
    ctx.body = 'ok';
  });

  app.get('/timeout', async ctx => {
    await sleep(500);
    ctx.body = 'timeout';
  });
};


<|start_filename|>test/fixtures/apps/singleton-demo/app.js<|end_filename|>
'use strict';

const createDataService = require('./create').sync;
const createDataServiceAsync = require('./create').async;

module.exports = app => {
  app.addSingleton('dataService', createDataService);
  app.addSingleton('dataServiceAsync', createDataServiceAsync);
};


<|start_filename|>test/fixtures/apps/body_parser_testapp/config/config.default.js<|end_filename|>
exports.bodyParser = {
  formLimit: '100kb',
  jsonLimit: '100kb',
  textLimit: '100kb',
  queryString: {
    arrayLimit: 5
  }
};

exports.keys = 'foo';


<|start_filename|>test/fixtures/apps/app-server-customized-client-error/config/config.default.js<|end_filename|>
'use strict';

const sleep = require('mz-modules/sleep');

exports.keys = 'my keys';

let times = 0;
exports.onClientError = async (err, socket, app) => {
  app.logger.error(err);
  await sleep(50);

  times++;
  if (times === 2) times = 0;
  if (!times) throw new Error('test throw');

  return {
    body: err.rawPacket,
    headers: { foo: 'bar', 'Content-Length': 100 },
    status: 418,
  };
};


<|start_filename|>test/app/extend/agent.test.js<|end_filename|>
'use strict';

const assert = require('assert');

const mm = require('egg-mock');
const utils = require('../../utils');

describe('test/app/extend/agent.test.js', () => {
  afterEach(mm.restore);

  describe('agent.addSingleton()', () => {
    let app;
    before(() => {
      app = utils.app('apps/singleton-demo');
      return app.ready();
    });
    after(() => app.close());

    it('should add singleton success', async () => {
      let config = await app.agent.dataService.get('second').getConfig();
      assert(config.foo === 'bar');
      assert(config.foo2 === 'bar2');

      const ds = app.agent.dataService.createInstance({ foo: 'barrr' });
      config = await ds.getConfig();
      assert(config.foo === 'barrr');

      const ds2 = await app.agent.dataService.createInstanceAsync({ foo: 'barrr' });
      config = await ds2.getConfig();
      assert(config.foo === 'barrr');

      config = await app.agent.dataServiceAsync.get('second').getConfig();
      assert(config.foo === 'bar');
      assert(config.foo2 === 'bar2');

      try {
        app.agent.dataServiceAsync.createInstance({ foo: 'barrr' });
        throw new Error('should not execute');
      } catch (err) {
        assert(err.message === 'egg:singleton dataServiceAsync only support create asynchronous, please use createInstanceAsync');
      }

      const ds4 = await app.agent.dataServiceAsync.createInstanceAsync({ foo: 'barrr' });
      config = await ds4.getConfig();
      assert(config.foo === 'barrr');
    });
  });
});


<|start_filename|>test/lib/core/messenger/local.test.js<|end_filename|>
'use strict';

const utils = require('../../../utils');
const pedding = require('pedding');
const assert = require('assert');
const mm = require('egg-mock');

describe('test/lib/core/messenger/local.test.js', () => {
  let app;

  before(async () => {
    app = await utils.singleProcessApp('apps/demo');
  });

  after(() => app.close());

  afterEach(() => {
    mm.restore();
    app.messenger.close();
    app.agent.messenger.close();
  });

  describe('broadcast()', () => {
    it('app.messenger.broadcast should work', done => {
      done = pedding(done, 2);
      app.messenger.once('broadcast-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });
      app.agent.messenger.once('broadcast-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.broadcast('broadcast-event', { foo: 'bar' });
    });

    it('agent.messenger.broadcast should work', done => {
      done = pedding(done, 2);
      app.messenger.once('broadcast-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });
      app.agent.messenger.once('broadcast-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.agent.messenger.broadcast('broadcast-event', { foo: 'bar' });
    });
  });

  describe('sendToApp()', () => {
    it('app.messenger.sendToApp should work', done => {
      app.agent.messenger.once('sendToApp-event', () => {
        throw new Error('should not emit on agent');
      });

      app.messenger.once('sendToApp-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.sendToApp('sendToApp-event', { foo: 'bar' });
    });

    it('agent.messenger.sendToApp should work', done => {
      app.agent.messenger.once('sendToApp-event', () => {
        throw new Error('should not emit on agent');
      });

      app.messenger.once('sendToApp-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.agent.messenger.sendToApp('sendToApp-event', { foo: 'bar' });
    });
  });

  describe('sendToAgent()', () => {
    it('app.messenger.sendToAgent should work', done => {
      app.agent.messenger.once('sendToAgent-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.once('sendToAgent-event', () => {
        throw new Error('should not emit on app');
      });

      app.messenger.sendToAgent('sendToAgent-event', { foo: 'bar' });
    });

    it('agent.messenger.sendToAgent should work', done => {
      app.agent.messenger.once('sendToAgent-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.once('sendToAgent-event', () => {
        throw new Error('should not emit on app');
      });

      app.agent.messenger.sendToAgent('sendToAgent-event', { foo: 'bar' });
    });
  });

  describe('sendRandom()', () => {
    it('app.messenger.sendRandom should work', done => {
      app.agent.messenger.once('sendRandom-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.once('sendRandom-event', () => {
        throw new Error('should not emit on app');
      });

      app.messenger.sendRandom('sendRandom-event', { foo: 'bar' });
    });

    it('agent.messenger.sendRandom should work', done => {
      app.agent.messenger.once('sendRandom-event', () => {
        throw new Error('should not emit on agent');
      });

      app.messenger.once('sendRandom-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.agent.messenger.sendRandom('sendRandom-event', { foo: 'bar' });
    });
  });

  describe('sendTo(pid)', () => {
    it('app.messenger.sendTo should work', done => {
      done = pedding(done, 2);
      app.messenger.once('sendTo-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });
      app.agent.messenger.once('sendTo-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      let res = app.messenger.sendTo(process.pid, 'sendTo-event', { foo: 'bar' });
      assert(res === app.messenger);
      // should ignore if target process is not self
      res = app.messenger.sendTo(1, 'sendTo-event', { foo: 'bar' });
      assert(res === app.messenger);
    });

    it('agent.messenger.sendTo should work', done => {
      done = pedding(done, 2);
      app.messenger.once('sendTo-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });
      app.agent.messenger.once('sendTo-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.agent.messenger.sendTo(process.pid, 'sendTo-event', { foo: 'bar' });
    });
  });

  describe('send()', () => {
    it('app.messenger.send should not throw when app.agent not exist', () => {
      mm(app, 'agent', undefined);
      app.messenger.send('send-event', { foo: 'bar' });
    });

    it('app.messenger.send should work', done => {
      app.agent.messenger.once('send-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.messenger.once('send-event', () => {
        throw new Error('should not emit on app');
      });

      app.messenger.send('send-event', { foo: 'bar' });
    });

    it('agent.messenger.send should work', done => {
      app.agent.messenger.once('send-event', () => {
        throw new Error('should not emit on agent');
      });

      app.messenger.once('send-event', msg => {
        assert.deepEqual(msg, { foo: 'bar' });
        done();
      });

      app.agent.messenger.send('send-event', { foo: 'bar' });
    });
  });

  describe('_onMessage()', () => {
    it('should ignore if message format error', () => {
      app.messenger._onMessage();
      app.messenger._onMessage('foo');
      app.messenger._onMessage({ action: 1 });
    });

    it('should emit with action', done => {
      app.messenger.once('test-action', done);
      app.messenger._onMessage({ action: 'test-action' });
    });
  });
});


<|start_filename|>lib/core/messenger/ipc.js<|end_filename|>
'use strict';

const debug = require('debug')('egg:util:messenger:ipc');
const is = require('is-type-of');
const sendmessage = require('sendmessage');
const EventEmitter = require('events');

/**
 * Communication between app worker and agent worker by IPC channel
 */
class Messenger extends EventEmitter {

  constructor() {
    super();
    this.pid = String(process.pid);
    // pids of agent or app maneged by master
    // - retrieve app worker pids when it's an agent worker
    // - retrieve agent worker pids when it's an app worker
    this.opids = [];
    this.on('egg-pids', pids => {
      this.opids = pids;
    });
    this._onMessage = this._onMessage.bind(this);
    process.on('message', this._onMessage);
  }

  /**
   * Send message to all agent and app
   * @param {String} action - message key
   * @param {Object} data - message value
   * @return {Messenger} this
   */
  broadcast(action, data) {
    debug('[%s] broadcast %s with %j', this.pid, action, data);
    this.send(action, data, 'app');
    this.send(action, data, 'agent');
    return this;
  }

  /**
   * send message to the specified process
   * @param {String} pid - the process id of the receiver
   * @param {String} action - message key
   * @param {Object} data - message value
   * @return {Messenger} this
   */
  sendTo(pid, action, data) {
    debug('[%s] send %s with %j to %s', this.pid, action, data, pid);
    sendmessage(process, {
      action,
      data,
      receiverPid: String(pid),
    });
    return this;
  }

  /**
   * send message to one app worker by random
   * - if it's running in agent, it will send to one of app workers
   * - if it's running in app, it will send to agent
   * @param {String} action - message key
   * @param {Object} data - message value
   * @return {Messenger} this
   */
  sendRandom(action, data) {
    /* istanbul ignore if */
    if (!this.opids.length) return this;
    const pid = random(this.opids);
    this.sendTo(String(pid), action, data);
    return this;
  }

  /**
   * send message to app
   * @param {String} action - message key
   * @param {Object} data - message value
   * @return {Messenger} this
   */
  sendToApp(action, data) {
    debug('[%s] send %s with %j to all app', this.pid, action, data);
    this.send(action, data, 'app');
    return this;
  }

  /**
   * send message to agent
   * @param {String} action - message key
   * @param {Object} data - message value
   * @return {Messenger} this
   */
  sendToAgent(action, data) {
    debug('[%s] send %s with %j to all agent', this.pid, action, data);
    this.send(action, data, 'agent');
    return this;
  }

  /**
   * @param {String} action - message key
   * @param {Object} data - message value
   * @param {String} to - let master know how to send message
   * @return {Messenger} this
   */
  send(action, data, to) {
    sendmessage(process, {
      action,
      data,
      to,
    });
    return this;
  }

  _onMessage(message) {
    if (message && is.string(message.action)) {
      debug('[%s] got message %s with %j, receiverPid: %s',
        this.pid, message.action, message.data, message.receiverPid);
      this.emit(message.action, message.data);
    }
  }

  close() {
    process.removeListener('message', this._onMessage);
    this.removeAllListeners();
  }

  /**
   * @method Messenger#on
   * @param {String} action - message key
   * @param {Object} data - message value
   */
}

module.exports = Messenger;

function random(arr) {
  const index = Math.floor(Math.random() * arr.length);
  return arr[index];
}


<|start_filename|>test/lib/core/loader/load_plugin.test.js<|end_filename|>
'use strict';

const path = require('path');
const fs = require('fs');
const mm = require('egg-mock');
const assert = require('assert');
const AppWorkerLoader = require('../../../../').AppWorkerLoader;
const AgentWorkerLoader = require('../../../../').AgentWorkerLoader;
const utils = require('../../../utils');

const EGG_BASE = path.join(__dirname, '../../../../');

describe('test/lib/core/loader/load_plugin.test.js', () => {
  let app;
  const logger = console;
  before(() => {
    app = utils.app('apps/empty');
    return app.ready();
  });
  after(() => app.close());
  afterEach(mm.restore);

  it('should loadConfig all plugins', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();
    assert.deepEqual(appLoader.plugins.b, {
      enable: true,
      name: 'b',
      dependencies: [],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'node_modules/b'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
    assert.deepEqual(appLoader.plugins.c, {
      enable: true,
      name: 'c',
      dependencies: [],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'node_modules/c'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
    assert.deepEqual(appLoader.plugins.e, {
      enable: true,
      name: 'e',
      dependencies: [ 'f' ],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'plugins/e'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
    assert(
      appLoader.plugins.onerror.path === fs.realpathSync(path.join(EGG_BASE, 'node_modules/egg-onerror'))
    );
    assert(appLoader.plugins.onerror.package === 'egg-onerror');
    assert(/\d+\.\d+\.\d+/.test(appLoader.plugins.onerror.version));
    assert(Array.isArray(appLoader.orderPlugins));
  });

  it('should same name plugin level follow: app > framework > egg', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();

    assert.deepEqual(appLoader.plugins.rds, {
      enable: true,
      name: 'rds',
      dependencies: [ 'session' ],
      optionalDependencies: [],
      env: [],
      package: 'rds',
      path: path.join(baseDir, 'node_modules/rds'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
  });

  it('should plguin support alias name', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();
    assert.deepEqual(appLoader.plugins.d1, {
      enable: true,
      name: 'd1',
      package: 'd',
      dependencies: [],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'node_modules/d'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
    assert(!appLoader.plugins.d);
  });

  it('should support package.json config', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();
    assert.deepEqual(appLoader.plugins.g, {
      enable: true,
      name: 'g',
      dependencies: [ 'f' ],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'plugins/g'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
  });

  it('should show warning message when plugin name wrong', () => {
    let message;
    mm(console, 'warn', m => {
      if (!m.startsWith('[egg:loader] pkg.eggPlugin is missing') && !message) {
        message = m;
      }
    });
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();

    assert(
      message === '[egg:loader] pluginName(e) is different from pluginConfigName(wrong-name)'
    );
  });

  it('should loadConfig plugins with custom plugins config', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const plugins = {
      foo: {
        enable: true,
        path: path.join(baseDir, 'node_modules/d'),
      },
      d1: {
        env: [ 'unittest' ],
      },
    };
    const appLoader = new AppWorkerLoader({
      baseDir,
      plugins,
      app,
      logger,
    });
    appLoader.loadConfig();

    assert.deepEqual(appLoader.plugins.d1, {
      enable: true,
      name: 'd1',
      package: 'd',
      dependencies: [],
      optionalDependencies: [],
      env: [ 'unittest' ],
      path: path.join(baseDir, 'node_modules/d'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
    assert.deepEqual(appLoader.plugins.foo, {
      enable: true,
      name: 'foo',
      dependencies: [],
      optionalDependencies: [],
      env: [],
      path: path.join(baseDir, 'node_modules/d'),
    });
    assert(!appLoader.plugins.d);
  });

  it('should throw error when plugin not exists', () => {
    assert.throws(function() {
      const baseDir = utils.getFilepath('apps/loader-plugin-noexist');
      const appLoader = new AppWorkerLoader({
        baseDir,
        app,
        logger,
      });
      appLoader.loadConfig();
    }, /Can not find plugin noexist in /);
  });

  it('should throw error when app baseDir not exists', () => {
    assert.throws(function() {
      const baseDir = utils.getFilepath('apps/notexist-app');
      const appLoader = new AppWorkerLoader({
        baseDir,
        app,
        logger,
      });
      appLoader.loadConfig();
    }, /notexist-app not exists/);
  });

  it('should keep plugin list sorted', () => {
    mm(process.env, 'NODE_ENV', 'development');
    const baseDir = utils.getFilepath('apps/loader-plugin-dep');
    const appLoader = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();
    assert.deepEqual(appLoader.orderPlugins.map(plugin => {
      return plugin.name;
    }), [
      'session',
      'security',
      'jsonp',
      'onerror',
      'i18n',
      'watcher',
      'schedule',
      'multipart',
      'development',
      'logrotator',
      'static',
      'view',
      'b',
      'c1',
      'f',
      'a',
      'd',
      'e',
    ]);
  });

  it('should throw recursive deps error', () => {
    assert.throws(function() {
      const baseDir = utils.getFilepath('apps/loader-plugin-dep-recursive');
      const appLoader = new AppWorkerLoader({
        baseDir,
        app,
        logger,
      });
      appLoader.loadConfig();
    }, /sequencify plugins has problem, missing: \[\], recursive: \[a,b,c,a\]/);
  });

  it('should throw error when plugin dep not exists', function() {
    assert.throws(function() {
      const baseDir = utils.getFilepath('apps/loader-plugin-dep-missing');
      const appLoader = new AppWorkerLoader({
        baseDir,
        app,
        logger,
      });
      appLoader.loadConfig();
    }, /sequencify plugins has problem, missing: \[a1\], recursive: \[\]\s+>> Plugin \[a1\] is disabled or missed, but is required by \[c\]/);
  });

  it('should auto fill plugin infos', () => {
    mm(process.env, 'NODE_ENV', 'test');
    const baseDir = utils.getFilepath('apps/loader-plugin');
    const appLoader1 = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader1.loadConfig();
    // unittest disable
    const keys1 = appLoader1.orderPlugins.map(plugin => {
      return plugin.name;
    }).join(',');
    assert(keys1.includes('b,c,d1,f,e'));
    assert(!appLoader1.plugins.a1);

    mm(process.env, 'NODE_ENV', 'development');
    const appLoader2 = new AppWorkerLoader({
      baseDir,
      app,
      logger,
    });
    appLoader2.loadConfig();
    const keys2 = appLoader2.orderPlugins.map(plugin => {
      return plugin.name;
    }).join(',');
    assert(keys2.includes('<KEY>'));
    assert.deepEqual(appLoader2.plugins.a1, {
      enable: true,
      name: 'a1',
      dependencies: [ 'd1' ],
      optionalDependencies: [],
      env: [ 'local', 'prod' ],
      path: path.join(baseDir, 'node_modules/a1'),
      from: path.join(baseDir, 'config/plugin.js'),
    });
  });

  it('should customize loadPlugin', () => {
    const baseDir = utils.getFilepath('apps/loader-plugin');
    class CustomAppLoader extends AppWorkerLoader {
      loadPlugin() {
        this.hasAppLoadPlugin = true;
        super.loadPlugin();
      }
    }
    const appLoader = new CustomAppLoader({
      baseDir,
      app,
      logger,
    });
    appLoader.loadConfig();
    assert(appLoader.hasAppLoadPlugin === true);

    class CustomAgentLoader extends AgentWorkerLoader {
      loadPlugin() {
        this.hasAgentLoadPlugin = true;
        super.loadPlugin();
      }
    }
    const agentLoader = new CustomAgentLoader({
      baseDir,
      app,
      logger,
    });
    agentLoader.loadConfig();
    assert(agentLoader.hasAgentLoadPlugin === true);
  });
});


<|start_filename|>test/fixtures/apps/custom-loader/app/controller/user.js<|end_filename|>
'use strict';

class UserController {
  constructor(ctx) {
    this.ctx = ctx;
    this.app = ctx.app;
  }

  async get() {
    this.ctx.body = {
      adapter: await this.app.adapter.docker.inspectDocker(),
      repository: await this.ctx.repository.user.get(),
    };
  }

  async beforeLoad() {
    this.ctx.body = this.app.beforeLoad;
  }
}

module.exports = UserController;


<|start_filename|>test/bench/hello/config/config.default.js<|end_filename|>
'use strict';

exports.keys = 'hello app';

exports.security = {
  csrf: false,
};


<|start_filename|>test/fixtures/apps/app-server-timeout/app.js<|end_filename|>
'use strict';

module.exports = app => {
  app.messenger.on('egg-ready', () => {
    // https://github.com/eggjs/egg/pull/3222
    // for general use, alinode will monitor all slow requests so you don't need to log it manually, just for showcase here.
    app.server.on('timeout', socket => {
      const req = socket.parser.incoming;
      if (req && socket._httpMessage) {
        app.coreLogger.warn('[http_server] A request `%s %s` timeout with client (%s:%d)', req.method, req.url, socket.remoteAddress, socket.remotePort);
      }
      socket.destroy();
    });
  });
};

<|start_filename|>test/fixtures/apps/dumpconfig/app.js<|end_filename|>
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const sleep = require('mz-modules/sleep');

function readJSON(p) {
  return JSON.parse(fs.readFileSync(p));
}

module.exports = app => {
  const baseDir = app.config.baseDir;
  let json;

  app.config.dynamic = 1;
  app.beforeStart(function*() {
    // dumpConfig() dynamically
    json = readJSON(path.join(baseDir, 'run/application_config.json'));
    assert(json.config.dynamic === 1, 'should dump in config');
    json = readJSON(path.join(baseDir, 'run/agent_config.json'));
    assert(json.config.dynamic === 0, 'should dump in config');

    yield sleep(2000);
    app.config.dynamic = 2;
  });
};


<|start_filename|>test/fixtures/apps/context-config-app/app/controller/home.js<|end_filename|>
'use strict';

exports.index = async ctx => {
  const router = ctx.router;
  // set router ok too
  ctx.router = router;
  ctx.body = {
    path: ctx.router.pathFor('home'),
    foo: ctx.foo,
    bar: ctx.bar()
  };
};


<|start_filename|>agent.js<|end_filename|>
'use strict';

const BaseHookClass = require('./lib/core/base_hook_class');

class EggAgentHook extends BaseHookClass {
  configDidLoad() {
    this.agent._wrapMessenger();
  }
}

module.exports = EggAgentHook;
