<commit_before>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as assert from 'assert';
const assertRejects = require('assert-rejects');
import * as child_process from 'child_process';
import * as crypto from 'crypto';
import * as fs from 'fs';
import {
  BASE_PATH,
  HEADERS,
  HOST_ADDRESS,
  SECONDARY_HOST_ADDRESS,
} from 'gcp-metadata';
import * as nock from 'nock';
import * as os from 'os';
import * as path from 'path';
import * as sinon from 'sinon';

import {GoogleAuth, JWT, UserRefreshClient} from '../src';
import {CredentialBody} from '../src/auth/credentials';
import * as envDetect from '../src/auth/envDetect';
import {Compute} from '../src/auth/computeclient';
import * as messages from '../src/messages';

nock.disableNetConnect();

const isWindows = process.platform === 'win32';

const tokenPath = `${BASE_PATH}/instance/service-accounts/default/token`;
const host = HOST_ADDRESS;
const instancePath = `${BASE_PATH}/instance`;
const svcAccountPath = `${instancePath}/service-accounts/?recursive=true`;
const API_KEY = 'test-123';
const STUB_PROJECT = 'my-awesome-project';
const ENDPOINT = '/events:report';
const RESPONSE_BODY = 'RESPONSE_BODY';
const BASE_URL = [
  'https://clouderrorreporting.googleapis.com/v1beta1/projects',
  STUB_PROJECT,
].join('/');

const privateJSON = require('../../test/fixtures/private.json');
const private2JSON = require('../../test/fixtures/private2.json');
const refreshJSON = require('../../test/fixtures/refresh.json');
const privateKey = fs.readFileSync('./test/fixtures/private.pem', 'utf-8');
const wellKnownPathWindows = path.join(
  'C:',
  'fake',
  'home',
  'gcloud',
  'application_default_credentials.json'
);
const wellKnownPathLinux = path.join(
  '/',
  'fake',
  'user',
  '.config',
  'gcloud',
  'application_default_credentials.json'
);

describe('googleauth', () => {
  let auth: GoogleAuth;
  const sandbox = sinon.createSandbox();
  let osStub: sinon.SinonStub<[], NodeJS.Platform>;
  let exposeWindowsWellKnownFile: boolean;
  let exposeLinuxWellKnownFile: boolean;
  let createLinuxWellKnownStream: Function;
  let createWindowsWellKnownStream: Function;
  beforeEach(() => {
    auth = new GoogleAuth();
    exposeWindowsWellKnownFile = false;
    exposeLinuxWellKnownFile = false;
    createLinuxWellKnownStream = () => {
      throw new Error();
    };
    createWindowsWellKnownStream = () => {
      throw new Error();
    };
    const envVars = Object.assign({}, process.env, {
      GCLOUD_PROJECT: undefined,
      GOOGLE_APPLICATION_CREDENTIALS: undefined,
      google_application_credentials: undefined,
      HOME: path.join('/', 'fake', 'user'),
    });
    sandbox.stub(process, 'env').value(envVars);
    osStub = sandbox.stub(os, 'platform').returns('linux');
    sandbox
      .stub(fs, 'existsSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .callsFake(() => exposeLinuxWellKnownFile)
      .withArgs(wellKnownPathWindows)
      .callsFake(() => exposeWindowsWellKnownFile);

    sandbox
      .stub(fs, 'createReadStream')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .callsFake(() => createLinuxWellKnownStream())
      .withArgs(wellKnownPathWindows)
      .callsFake(() => createWindowsWellKnownStream());

    sandbox
      .stub(fs, 'realpathSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .returnsArg(0)
      .withArgs(wellKnownPathWindows)
      .returnsArg(0);

    sandbox
      .stub(child_process, 'exec')
      .callThrough()
      .withArgs('gcloud config config-helper --format json', sinon.match.func)
      .callsArgWith(1, null, '', null);

    const fakeStat = {isFile: () => true} as fs.Stats;
    sandbox
      .stub(fs, 'lstatSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .returns(fakeStat)
      .withArgs(wellKnownPathWindows)
      .returns(fakeStat);
  });

  afterEach(() => {
    nock.cleanAll();
    sandbox.restore();
  });

  function mockWindows() {
    osStub.returns('win32');
    process.env.HOME = '';
    process.env.APPDATA = path.join('C:', 'fake', 'home');
  }

  function mockWindowsWellKnownFile() {
    exposeWindowsWellKnownFile = true;
    createWindowsWellKnownStream = () =>
      fs.createReadStream('./test/fixtures/private2.json');
  }

  function mockLinuxWellKnownFile() {
    exposeLinuxWellKnownFile = true;
    createLinuxWellKnownStream = () =>
      fs.createReadStream('./test/fixtures/private2.json');
  }

  function nockIsGCE() {
    const primary = nock(host)
      .get(instancePath)
      .reply(200, {}, HEADERS);
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .reply(200, {}, HEADERS);

    return {
      done: () => {
        primary.done();
        secondary.done();
      },
    };
  }

  function nockNotGCE() {
    const primary = nock(host)
      .get(instancePath)
      .replyWithError({code: 'ENOTFOUND'});
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .replyWithError({code: 'ENOTFOUND'});
    return {
      done: () => {
        primary.done();
        secondary.done();
      },
    };
  }

  function nock500GCE() {
    const primary = nock(host)
      .get(instancePath)
      .reply(500, {}, HEADERS);
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .reply(500, {}, HEADERS);

    return {<commit_msg>test: address race condition in tests (#815)<commit_after>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as assert from 'assert';
const assertRejects = require('assert-rejects');
import * as child_process from 'child_process';
import * as crypto from 'crypto';
import * as fs from 'fs';
import {
  BASE_PATH,
  HEADERS,
  HOST_ADDRESS,
  SECONDARY_HOST_ADDRESS,
} from 'gcp-metadata';
import * as nock from 'nock';
import * as os from 'os';
import * as path from 'path';
import * as sinon from 'sinon';

import {GoogleAuth, JWT, UserRefreshClient} from '../src';
import {CredentialBody} from '../src/auth/credentials';
import * as envDetect from '../src/auth/envDetect';
import {Compute} from '../src/auth/computeclient';
import * as messages from '../src/messages';

nock.disableNetConnect();

const isWindows = process.platform === 'win32';

const tokenPath = `${BASE_PATH}/instance/service-accounts/default/token`;
const host = HOST_ADDRESS;
const instancePath = `${BASE_PATH}/instance`;
const svcAccountPath = `${instancePath}/service-accounts/?recursive=true`;
const API_KEY = 'test-123';
const STUB_PROJECT = 'my-awesome-project';
const ENDPOINT = '/events:report';
const RESPONSE_BODY = 'RESPONSE_BODY';
const BASE_URL = [
  'https://clouderrorreporting.googleapis.com/v1beta1/projects',
  STUB_PROJECT,
].join('/');

const privateJSON = require('../../test/fixtures/private.json');
const private2JSON = require('../../test/fixtures/private2.json');
const refreshJSON = require('../../test/fixtures/refresh.json');
const privateKey = fs.readFileSync('./test/fixtures/private.pem', 'utf-8');
const wellKnownPathWindows = path.join(
  'C:',
  'fake',
  'home',
  'gcloud',
  'application_default_credentials.json'
);
const wellKnownPathLinux = path.join(
  '/',
  'fake',
  'user',
  '.config',
  'gcloud',
  'application_default_credentials.json'
);

describe('googleauth', () => {
  let auth: GoogleAuth;
  const sandbox = sinon.createSandbox();
  let osStub: sinon.SinonStub<[], NodeJS.Platform>;
  let exposeWindowsWellKnownFile: boolean;
  let exposeLinuxWellKnownFile: boolean;
  let createLinuxWellKnownStream: Function;
  let createWindowsWellKnownStream: Function;
  beforeEach(() => {
    auth = new GoogleAuth();
    exposeWindowsWellKnownFile = false;
    exposeLinuxWellKnownFile = false;
    createLinuxWellKnownStream = () => {
      throw new Error();
    };
    createWindowsWellKnownStream = () => {
      throw new Error();
    };
    const envVars = Object.assign({}, process.env, {
      GCLOUD_PROJECT: undefined,
      GOOGLE_APPLICATION_CREDENTIALS: undefined,
      google_application_credentials: undefined,
      HOME: path.join('/', 'fake', 'user'),
    });
    sandbox.stub(process, 'env').value(envVars);
    osStub = sandbox.stub(os, 'platform').returns('linux');
    sandbox
      .stub(fs, 'existsSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .callsFake(() => exposeLinuxWellKnownFile)
      .withArgs(wellKnownPathWindows)
      .callsFake(() => exposeWindowsWellKnownFile);

    sandbox
      .stub(fs, 'createReadStream')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .callsFake(() => createLinuxWellKnownStream())
      .withArgs(wellKnownPathWindows)
      .callsFake(() => createWindowsWellKnownStream());

    sandbox
      .stub(fs, 'realpathSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .returnsArg(0)
      .withArgs(wellKnownPathWindows)
      .returnsArg(0);

    sandbox
      .stub(child_process, 'exec')
      .callThrough()
      .withArgs('gcloud config config-helper --format json', sinon.match.func)
      .callsArgWith(1, null, '', null);

    const fakeStat = {isFile: () => true} as fs.Stats;
    sandbox
      .stub(fs, 'lstatSync')
      .callThrough()
      .withArgs(wellKnownPathLinux)
      .returns(fakeStat)
      .withArgs(wellKnownPathWindows)
      .returns(fakeStat);
  });

  afterEach(() => {
    nock.cleanAll();
    sandbox.restore();
  });

  function mockWindows() {
    osStub.returns('win32');
    process.env.HOME = '';
    process.env.APPDATA = path.join('C:', 'fake', 'home');
  }

  function mockWindowsWellKnownFile() {
    exposeWindowsWellKnownFile = true;
    createWindowsWellKnownStream = () =>
      fs.createReadStream('./test/fixtures/private2.json');
  }

  function mockLinuxWellKnownFile() {
    exposeLinuxWellKnownFile = true;
    createLinuxWellKnownStream = () =>
      fs.createReadStream('./test/fixtures/private2.json');
  }

  function nockIsGCE() {
    const primary = nock(host)
      .get(instancePath)
      .reply(200, {}, HEADERS);
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .reply(200, {}, HEADERS);

    return {
      done: () => {
        try {
          primary.done();
          secondary.done();
        } catch (_err) {
          // secondary can sometimes complete prior to primary.
        }
      },
    };
  }

  function nockNotGCE() {
    const primary = nock(host)
      .get(instancePath)
      .replyWithError({code: 'ENOTFOUND'});
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .replyWithError({code: 'ENOTFOUND'});
    return {
      done: () => {
        try {
          primary.done();
          secondary.done();
        } catch (_err) {
          // secondary can sometimes complete prior to primary.
        }
      },
    };
  }

  function nock500GCE() {
    const primary = nock(host)
      .get(instancePath)
      .reply(500, {}, HEADERS);
    const secondary = nock(SECONDARY_HOST_ADDRESS)
      .get(instancePath)
      .reply(500, {}, HEADERS);

    return {
{'fraction_non_alphanumeric': 0.13995893223819303, 'fraction_numerical': 0.006817248459958933, 'mean_word_length': 3.3814321698452683, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '321515', 'n_tokens_mistral': 3903, 'n_tokens_neox': 3769, 'n_words': 846}