<commit_before>#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var figures = require('figures');
var flatten = require('arr-flatten');
var globby = require('globby');
var meow = require('meow');
var updateNotifier = require('update-notifier');
var chalk = require('chalk');
var Promise = require('bluebird');
var fork = require('./lib/fork');
var log = require('./lib/logger');

// Bluebird specific
Promise.longStackTraces();

var cli = meow({
	help: [
		'Usage',
		'  ava [<file|folder|glob> ...]',
		'',
		'Options',
		'  --init       Add AVA to your project',
		'  --fail-fast  Stop after first test failure',
		'  --serial     Run tests serially',
		'',
		'Examples',
		'  ava',
		'  ava test.js test2.js',
		'  ava test-*.js',
		'  ava --init',
		'  ava --init foo.js',
		'',
		'Default patterns when no arguments:',
		'test.js test-*.js test/*.js'
	]
}, {
	string: ['_'],
	boolean: [
		'fail-fast',
		'serial'
	]
});

var testCount = 0;
var fileCount = 0;
var unhandledRejectionCount = 0;
var uncaughtExceptionCount = 0;
var errors = [];

function error(err) {
	console.error(err.stack);
	process.exit(1);
}

function prefixTitle(file) {
	var separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';

	var base = path.dirname(cli.input[0]);

	if (base === '.') {
		base = cli.input[0] || 'test';
	}

	base += path.sep;

	var prefix = path.relative(process.cwd(), file)
		.replace(/test\-/g, '')
		.replace(/\.js$/, '')
		.replace(base, '')
		.split(path.sep).join(separator);

	if (prefix.length > 0) {
		prefix += separator;
	}

	return prefix;
}

function stats(stats) {
	testCount += stats.testCount;
}

function test(data) {
	var isError = data.error.message;

	if (fileCount > 1) {
		data.title = prefixTitle(data.file) + data.title;
	}

	if (isError) {
		log.error(data.title, chalk.red(data.error.message));

		errors.push(data);
	} else {
		// if there's only one file and one anonymous test
		// don't log it
		if (fileCount === 1 && testCount === 1 && data.title === '[anonymous]') {
			return;
		}

		log.test(data);
	}
}

function run(file) {
	var args = [file];

	if (cli.flags.failFast) {
		args.push('--fail-fast');
	}

	if (cli.flags.serial) {
		args.push('--serial');
	}

	return fork(args)
		.on('stats', stats)
		.on('test', test)
		.on('unhandledRejections', rejections)
		.on('uncaughtException', uncaughtException)
		.on('data', function (data) {
			process.stdout.write(data);
		});
}

function rejections(data) {
	var unhandled = data.unhandledRejections;
	log.unhandledRejections(data.file, unhandled);
	unhandledRejectionCount += unhandled.length;
}

function uncaughtException(data) {
	uncaughtExceptionCount++;
	log.uncaughtException(data.file, data.uncaughtException);
}

function sum(arr, key) {
	var result = 0;

	arr.forEach(function (item) {
		result += item[key];
	});

	return result;
}

function exit(results) {
	// assemble stats from all tests
	var stats = results.map(function (result) {
		return result.stats;
	});

	var tests = results.map(function (result) {
		return result.tests;
	});

	var passed = sum(stats, 'passCount');
	var failed = sum(stats, 'failCount');

	log.write();
	log.report(passed, failed, unhandledRejectionCount, uncaughtExceptionCount);
	log.write();

	if (failed > 0) {
		log.errors(flatten(tests));
	}

	// TODO: figure out why this needs to be here to
	// correctly flush the output when multiple test files
	process.stdout.write('');

	// timeout required to correctly flush stderr on Node 0.10 Windows
	setTimeout(function () {
		process.exit(failed > 0 || unhandledRejectionCount > 0 || uncaughtExceptionCount > 0 ? 1 : 0);
	}, 0);
}

function init(files) {
	log.write();<commit_msg>make shure IO streams are flushed before exiting a process.<commit_after>#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var figures = require('figures');
var flatten = require('arr-flatten');
var globby = require('globby');
var meow = require('meow');
var updateNotifier = require('update-notifier');
var chalk = require('chalk');
var Promise = require('bluebird');
var fork = require('./lib/fork');
var log = require('./lib/logger');

// Bluebird specific
Promise.longStackTraces();

var cli = meow({
	help: [
		'Usage',
		'  ava [<file|folder|glob> ...]',
		'',
		'Options',
		'  --init       Add AVA to your project',
		'  --fail-fast  Stop after first test failure',
		'  --serial     Run tests serially',
		'',
		'Examples',
		'  ava',
		'  ava test.js test2.js',
		'  ava test-*.js',
		'  ava --init',
		'  ava --init foo.js',
		'',
		'Default patterns when no arguments:',
		'test.js test-*.js test/*.js'
	]
}, {
	string: ['_'],
	boolean: [
		'fail-fast',
		'serial'
	]
});

var testCount = 0;
var fileCount = 0;
var unhandledRejectionCount = 0;
var uncaughtExceptionCount = 0;
var errors = [];

function error(err) {
	console.error(err.stack);
	flushIoAndExit(1);
}

function prefixTitle(file) {
	var separator = ' ' + chalk.gray.dim(figures.pointerSmall) + ' ';

	var base = path.dirname(cli.input[0]);

	if (base === '.') {
		base = cli.input[0] || 'test';
	}

	base += path.sep;

	var prefix = path.relative(process.cwd(), file)
		.replace(/test\-/g, '')
		.replace(/\.js$/, '')
		.replace(base, '')
		.split(path.sep).join(separator);

	if (prefix.length > 0) {
		prefix += separator;
	}

	return prefix;
}

function stats(stats) {
	testCount += stats.testCount;
}

function test(data) {
	var isError = data.error.message;

	if (fileCount > 1) {
		data.title = prefixTitle(data.file) + data.title;
	}

	if (isError) {
		log.error(data.title, chalk.red(data.error.message));

		errors.push(data);
	} else {
		// if there's only one file and one anonymous test
		// don't log it
		if (fileCount === 1 && testCount === 1 && data.title === '[anonymous]') {
			return;
		}

		log.test(data);
	}
}

function run(file) {
	var args = [file];

	if (cli.flags.failFast) {
		args.push('--fail-fast');
	}

	if (cli.flags.serial) {
		args.push('--serial');
	}

	return fork(args)
		.on('stats', stats)
		.on('test', test)
		.on('unhandledRejections', rejections)
		.on('uncaughtException', uncaughtException)
		.on('data', function (data) {
			process.stdout.write(data);
		});
}

function rejections(data) {
	var unhandled = data.unhandledRejections;
	log.unhandledRejections(data.file, unhandled);
	unhandledRejectionCount += unhandled.length;
}

function uncaughtException(data) {
	uncaughtExceptionCount++;
	log.uncaughtException(data.file, data.uncaughtException);
}

function sum(arr, key) {
	var result = 0;

	arr.forEach(function (item) {
		result += item[key];
	});

	return result;
}

function exit(results) {
	// assemble stats from all tests
	var stats = results.map(function (result) {
		return result.stats;
	});

	var tests = results.map(function (result) {
		return result.tests;
	});

	var passed = sum(stats, 'passCount');
	var failed = sum(stats, 'failCount');

	log.write();
	log.report(passed, failed, unhandledRejectionCount, uncaughtExceptionCount);
	log.write();

	if (failed > 0) {
		log.errors(flatten(tests));
	}

	process.stdout.write('');

	flushIoAndExit(
		failed > 0 || unhandledRejectionCount > 0 || uncaughtExceptionCount > 0 ? 1 : 0
	);
}

function flushIoAndExit(code) {
	// TODO: figure out why this needs to be here to
	// correctly flush the output when multiple test files
	process.stdout.write('');
	process.stderr.write('');

	// timeout required to correctly flush io on Node 0.10 Windows
	setTimeout(function () {
		process.exit(code);
	}, 0);
}

function init(files) {
	log.write();
{'fraction_non_alphanumeric': 0.17534355179704017, 'fraction_numerical': 0.006078224101479916, 'mean_word_length': 3.7100186683260734, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '4270638', 'n_tokens_mistral': 2883, 'n_tokens_neox': 2658, 'n_words': 630}