text:
<?php

namespace johnitvn\userplus\basic\models;

use Yii;
use yii\helpers\Url;
use johnitvn\userplus\Helper;
use johnitvn\userplus\basic\UserConfirmableInterface;
use johnitvn\userplus\basic\UserRecoveryableInterface;
use johnitvn\userplus\base\models\UserAccounts as BaseUserAccounts;

/**
 *
 * @author John Martin <john.itvn@gmail.com>
 * @since 1.0.0
 */
class UserAccounts extends BaseUserAccounts implements UserConfirmableInterface, UserRecoveryableInterface {

    /**
     * @var User Accounts Event
     */
    const BEFORE_RESET_PASSWORD = 'beforeResetPassword';

    /**
     * @var User Accounts Event
     */
    const AFTER_RESET_PASSWORD = 'afterResetPassword';

    /**
     * @var User Accounts Event
     */
    const BEFORE_CONFIRM = 'beforeConfirm';

    /**
     * @var User Accounts Event
     */
    const AFTER_CONFIRM = 'afterConfirm';

    /**
     * @var User Accounts Event
     */
    const BEFORE_RECONFIRM = 'beforeReconfirm';

    /**
     * @var User Accounts Event
     */
    const AFTER_RECONFIRM = 'afterReconfirm';

    /**
     * @var User Accounts Event
     */
    const BEFORE_RECOVERY = 'beforeRecovery';

    /**
     * @var User Accounts Event
     */
    const AFTER_RECOVERY = 'afterRecovery';

    /**
     * Instace of johnitvn\userplus\basic\Mailer
     * @var johnitvn\userplus\basic\Mailer
     */
    protected $mailer;

    /**
     * @inheritdoc
     */
    public function init() {
        parent::init();
        $this->mailer = $this->userPlusModule->mailer;
        $this->on(self::AFTER_REGISTER, [$this, 'afterRegister']);
        $this->on(self::AFTER_RECOVERY, [$this, 'afterRecovery']);
        $this->on(self::AFTER_RESET_PASSWORD, [$this, 'afterResetPassword']);
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        $rules = parent::rules();
        $rules['usernameRequired'] = ['username', 'required'];
        $rules['usernamePattern'] = ['username', 'match', 'pattern' => '/^[-a-zA-Z0-9_\.@]+$/'];
        $rules['usernameLength'] = ['username', 'string', 'min' => 3, 'max' => 255];
        $rules['usernameUnique'] = ['username', 'unique', 'message' => Yii::t('user', 'This username has already been taken')];

        $rules['loginUnique'] = ['login', 'unique', 'message' => Yii::t('user', 'This email has already been taken for other account')];
        $rules['loginPattern'] = ['login', 'email'];
        return $rules;
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        $labels = parent::attributeLabels();
        $labels['login'] = Yii::t('user', 'Email');
        $labels['username'] = Yii::t('user', 'Username');
        return $labels;
    }

    public function scenarios() {
        $scenarios = parent::scenarios();
        $scenarios['register'][] = 'username';
        $scenarios['create'][] = 'username';
        $scenarios['console-create'][] = 'username';
        $scenarios['confirm'] = ['confirm_token', 'confirmed_at'];
        $scenarios['recovery'] = ['recovery_token'];
        $scenarios['reset-password'] = ['password'];
        return $scenarios;
    }

    /**
     * Get username of user
     * @return string Return the username of use
     */
    public function getUsername() {
        return $this->username;
    }

    /**
     * Do all jobs after register
     * @return boolean
     */
    public function afterRegister() {
        if ($this->userPlusModule->enableConfirmation) {
            $token = $this->generateConfirmToken();
            $route = $this->userPlusModule->confirmationHandlerRoute;
            $url = Url::to([$route, 'token' => $token], true);
            if (!$this->save()) {
                return false;
            }
            $this->mailer->sendConfirmationMessage($this, ['url' => $url]);
        }
    }

    /**
     * Find user by login field
     *
     * @param string email/username to find
     * @return boolean|UserAccounts
     */
    public static function findIdentityByLogin($login) {
        $userPlusModule = \Yii::$app->getModule('user');
        if ($userPlusModule->loginType == "username") {
            $model = static::findOne(['username' => $login]);
        } else {
            $model = static::findOne(['login' => $login]);
        }
        return $model;
    }

    public static function findIdentityByEmail($email) {
        return static::findOne(['login' => $email]);
    }

    /**
     *
     * @return boolean
     */
    public function isConfirmed() {
        return $this->confirmed_at !== null;
    }

    /**
     *
     * @return string
     */
    public function getEmail() {
        return $this->login;
    }

    /**
     *
     * @return boolean
     */
    public function confirm() {
        $this->trigger(self::BEFORE_CONFIRM);
        $this->scenario = 'confirm';
        $this->confirm_token = null;
        $this->confirmed_at = time();
        if (!$this->save()) {
            return false;
        }
        $this->trigger(self::AFTER_CONFIRM);
        return true;
    }

    /**
     *
     * @return boolean
     */
    public function recovery() {
        $this->trigger(self::BEFORE_RECOVERY);
        $this->generateRecoveryToken();
        if (!$this->save()) {
            return false;
        }
        $this->trigger(self::AFTER_RECOVERY);
        return true;
    }

    /**
     * Do all jobs when after recovery
     */
    public function afterRecovery() {
        $token = $this->recovery_token;
        $route = $this->userPlusModule->resetPasswordHandlerRoute;
        $url = Url::to([$route, 'token' => $token], true);
        $this->mailer->sendRecoveryMessage($this, ['url' => $url]);
    }

    /**
     *
     * @return boolean
     */
    public function resetPassword() {
        $this->trigger(self::BEFORE_RESET_PASSWORD);
        $this->scenario = 'reset-password';
        $this->password = Helper::generatePassword();
        if (!$this->save()) {
            return false;
        }

        $this->trigger(self::AFTER_RESET_PASSWORD);
        return true;
    }

    /**
     *
     */
    public function afterResetPassword() {
        $this->mailer->sendResetPasswordMessage($this, ['password' => $this->password]);
    }

    /**
     *
     * @return boolean
     */
    public function resendConfirmation() {
        $this->trigger(self::BEFORE_RECONFIRM);
        $token = $this->generateConfirmToken();
        $route = $this->userPlusModule->confirmationHandlerRoute;
        $url = Url::to([$route, 'token' => $token], true);
        if (!$this->save()) {
            return false;
        }
        $this->mailer->sendReconfirmationMessage($this, ['url' => $url]);
        $this->trigger(self::AFTER_RECONFIRM);
        return true;
    }

    /**
     *
     * @return string
     */
    public function generateConfirmToken() {
        $token = Helper::generateRandomString($this->userPlusModule->tokenLenght);
        $this->confirm_token = $token;
        return $this->confirm_token;
    }

    /**
     *
     * @return string
     */
    public function generateRecoveryToken() {
        $token = Helper::generateRandomString($this->userPlusModule->tokenLenght);
        $this->recovery_token = $token;
        return $this->recovery_token;
    }

    /**
     *
     * @param string $token
     * @return UserAccounts
     */
    public static function findIdentityByConfirmToken($token) {
        return UserAccounts::findOne(['confirm_token' => $token]);
    }

    /**
     *
     * @param string $token
     * @return UserAccounts
     */
    public static function findIdentityByRecoveryToken($token) {
        return UserAccounts::findOne(['recovery_token' => $token]);
    }

}


text:
require 'thread'
require 'fake_env/version'

module FakeEnv
  class << self
    attr_reader :actual, :fake, :actual_get_method, :actual_set_method

    def activate!
      @actual = ENV.clone
      @fake = Hash.new do |fake, key|
        val = @actual[key]

        fake[key] = val ? val : val.clone
      end

      @actual_get_method ||= ENV.method(:[])
      @actual_set_method ||= ENV.method(:[]=)

      class << ENV
        def [](key)
          FakeEnv.fake[key]
        end

        def []=(key, val)
          FakeEnv.fake[key] = val.freeze
        end
      end
    end

    def deactivate!
      class << ENV
        define_method(:[], FakeEnv.actual_get_method)
        define_method(:[]=, FakeEnv.actual_set_method)
      end
    end

    def within
      activate!
      yield if block_given?
    ensure
      deactivate!
    end
  end
end

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace HumusStreamResponseSenderTest;

use HumusStreamResponseSender\Controller\Plugin\Stream;
use PHPUnit\Framework\TestCase;

class StreamTest extends TestCase
{
    public function testBinaryFile()
    {
        $utt = new Stream();
        $filename = __DIR__ . '/../../TestAsset/sample-stream-file.txt';
        $filesize = filesize($filename);
        $basename = basename($filename);
        $lastModified = new \DateTime();
        $lastModified->setTimestamp(filemtime($filename));
        $lastModified = $lastModified->format(\DateTime::RFC1123);

        $response = $utt->binaryFile($filename);
        $this->assertInstanceOf('Zend\Http\Response\Stream', $response);
        $this->assertInternalType('resource', $response->getStream());
        $this->assertSame($basename, $response->getStreamName());
        $this->assertSame($filesize, $response->getContentLength());
        $headers = $response->getHeaders()->toArray();
        $expectedHeaders = array(
            'Content-Disposition' => 'attachment; filename="' . $basename . '"',
            'Content-Type' => 'application/octet-stream',
            'Last-Modified' => $lastModified
        );
        $this->assertSame($expectedHeaders, $headers);
    }
}


text:
var path = require('path');
var url = require('url');

var DOUBLE_QUOTE = '"';
var SINGLE_QUOTE = '\'';
var URL_PREFIX = 'url(';
var URL_SUFFIX = ')';

var QUOTE_PREFIX_PATTERN = /^["']/;
var QUOTE_SUFFIX_PATTERN = /["']$/;
var ROUND_BRACKETS_PATTERN = /[\(\)]/;
var URL_PREFIX_PATTERN = /^url\(/i;
var URL_SUFFIX_PATTERN = /\)$/;
var WHITESPACE_PATTERN = /\s/;

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

function rebase(uri, rebaseConfig) {
  if (!rebaseConfig) {
    return uri;
  }

  if (isAbsolute(uri) && !isRemote(rebaseConfig.toBase)) {
    return uri;
  }

  if (isRemote(uri) || isSVGMarker(uri) || isInternal(uri)) {
    return uri;
  }

  if (isData(uri)) {
    return '\'' + uri + '\'';
  }

  if (isRemote(rebaseConfig.toBase)) {
    return url.resolve(rebaseConfig.toBase, uri);
  }

  return rebaseConfig.absolute ?
    normalize(absolute(uri, rebaseConfig)) :
    normalize(relative(uri, rebaseConfig));
}

function isAbsolute(uri) {
  return path.isAbsolute(uri);
}

function isSVGMarker(uri) {
  return uri[0] == '#';
}

function isInternal(uri) {
  return /^\w+:\w+/.test(uri);
}

function isRemote(uri) {
  return /^[^:]+?:\/\//.test(uri) || uri.indexOf('//') === 0;
}

function isData(uri) {
  return uri.indexOf('data:') === 0;
}

function absolute(uri, rebaseConfig) {
  return path
    .resolve(path.join(rebaseConfig.fromBase || '', uri))
    .replace(rebaseConfig.toBase, '');
}

function relative(uri, rebaseConfig) {
  return path.relative(rebaseConfig.toBase, path.join(rebaseConfig.fromBase || '', uri));
}

function normalize(uri) {
  return isWindows ? uri.replace(/\\/g, '/') : uri;
}

function quoteFor(unquotedUrl) {
  if (unquotedUrl.indexOf(SINGLE_QUOTE) > -1) {
    return DOUBLE_QUOTE;
  } else if (unquotedUrl.indexOf(DOUBLE_QUOTE) > -1) {
    return SINGLE_QUOTE;
  } else if (hasWhitespace(unquotedUrl) || hasRoundBrackets(unquotedUrl)) {
    return SINGLE_QUOTE;
  } else {
    return '';
  }
}

function hasWhitespace(url) {
  return WHITESPACE_PATTERN.test(url);
}

function hasRoundBrackets(url) {
  return ROUND_BRACKETS_PATTERN.test(url);
}

function rewriteUrl(originalUrl, rebaseConfig, pathOnly) {
  var strippedUrl = originalUrl
    .replace(URL_PREFIX_PATTERN, '')
    .replace(URL_SUFFIX_PATTERN, '')
    .trim();

  var unquotedUrl = strippedUrl
    .replace(QUOTE_PREFIX_PATTERN, '')
    .replace(QUOTE_SUFFIX_PATTERN, '')
    .trim();

  var quote = strippedUrl[0] == SINGLE_QUOTE || strippedUrl[0] == DOUBLE_QUOTE ?
    strippedUrl[0] :
    quoteFor(unquotedUrl);

  return pathOnly ?
    rebase(unquotedUrl, rebaseConfig) :
    URL_PREFIX + quote + rebase(unquotedUrl, rebaseConfig) + quote + URL_SUFFIX;
}

module.exports = rewriteUrl;


text:
<?xml version="1.0" encoding="UTF-8"?>

<phpunit bootstrap="tests/bootstrap.php" colors="true">
  <testsuites>
    <testsuite>
      <directory suffix="Test.php">tests</directory>
    </testsuite>
  </testsuites>
  <logging>
    <log type="coverage-html" target="build/coverage" />
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml"/>
  </logging>
  <filter>
      <whitelist>
          <directory suffix=".php">src</directory>
      </whitelist>
  </filter>
</phpunit>


text:
package com.pepedyne.pepe.servos;

public class EyeColorServo extends StandardServo {

   public static int BLACK = 0;
   public static int AQUA = 1;
   public static int RED = 2;
   public static int WHITE = 3;
   public static int BLUE = 4;
   public static int GREEN = 5;
   public static int YELLOW = 6;
   public static int MAGENTA = 7;
   public static int PURPLE = 8;
   public static int ORANGE = 9;

   public EyeColorServo(String name, int min, int max) {
      super(name, min, max);
      this.current = max;
   }

   public void eyeOff() {
      this.current = 0;
   }

   public void eyeOn() {
      this.current = this.getLimit().getMax();
   }

   public void setColor(int value) {
      this.current = value;
   }

}


text:
import * as assert from 'assert';
import * as lifecycle from 'vs/base/common/lifecycle';
import * as _ from 'vs/base/parts/tree/browser/tree';
import * as model from 'vs/base/parts/tree/browser/treeModel';
import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults';
import { Event, Emitter } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';

export class FakeRenderer {

	public getHeight(tree: _.ITree, element: any): number {
		return 20;
	}

	public getTemplateId(tree: _.ITree, element: any): string {
		return 'fake';
	}

	public renderTemplate(tree: _.ITree, templateId: string, container: any): any {
		return null;
	}

	public renderElement(tree: _.ITree, element: any, templateId: string, templateData: any): void {
		// noop
	}

	public disposeTemplate(tree: _.ITree, templateId: string, templateData: any): void {
		// noop
	}
}

class TreeContext implements _.ITreeContext {

	public tree: _.ITree = null!;
	public options: _.ITreeOptions = { autoExpandSingleChildren: true };
	public dataSource: _.IDataSource;
	public renderer: _.IRenderer;
	public controller?: _.IController;
	public dnd?: _.IDragAndDrop;
	public filter: _.IFilter;
	public sorter: _.ISorter;

	constructor(public configuration: _.ITreeConfiguration) {
		this.dataSource = configuration.dataSource;
		this.renderer = configuration.renderer || new FakeRenderer();
		this.controller = configuration.controller;
		this.dnd = configuration.dnd;
		this.filter = configuration.filter || new TreeDefaults.DefaultFilter();
		this.sorter = configuration.sorter || new TreeDefaults.DefaultSorter();
	}
}

class TreeModel extends model.TreeModel {

	constructor(configuration: _.ITreeConfiguration) {
		super(new TreeContext(configuration));
	}
}

class EventCounter {

	private listeners: lifecycle.IDisposable[];
	private _count: number;

	constructor() {
		this.listeners = [];
		this._count = 0;
	}

	public listen<T>(event: Event<T>, fn: ((e: T) => void) | null = null): () => void {
		let r = event(data => {
			this._count++;
			if (fn) {
				fn(data);
			}
		});

		this.listeners.push(r);

		return () => {
			let idx = this.listeners.indexOf(r);
			if (idx > -1) {
				this.listeners.splice(idx, 1);
				r.dispose();
			}
		};
	}

	public up(): void {
		this._count++;
	}

	public get count(): number {
		return this._count;
	}

	public dispose(): void {
		this.listeners = lifecycle.dispose(this.listeners);
		this._count = -1;
	}
}

const SAMPLE: any = {
	ONE: { id: 'one' },

	AB: {
		id: 'ROOT', children: [
			{
				id: 'a', children: [
					{ id: 'aa' },
					{ id: 'ab' }
				]
			},
			{ id: 'b' },
			{
				id: 'c', children: [
					{ id: 'ca' },
					{ id: 'cb' }
				]
			}
		]
	},

	DEEP: {
		id: 'ROOT', children: [
			{
				id: 'a', children: [
					{
						id: 'x', children: [
							{ id: 'xa' },
							{ id: 'xb' },
						]
					}
				]
			},
			{ id: 'b' }
		]
	},

	DEEP2: {
		id: 'ROOT', children: [
			{
				id: 'a', children: [
					{
						id: 'x', children: [
							{ id: 'xa' },
							{ id: 'xb' },
						]
					},
					{ id: 'y' }
				]
			},
			{ id: 'b' }
		]
	}
};

class TestDataSource implements _.IDataSource {
	public getId(tree, element): string {
		return element.id;
	}

	public hasChildren(tree, element): boolean {
		return !!element.children;
	}

	public getChildren(tree, element): Promise<any> {
		return Promise.resolve(element.children);
	}

	public getParent(tree, element): Promise<any> {
		throw new Error('Not implemented');
	}
}

suite('TreeModel', () => {
	let model: model.TreeModel;
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
		model = new TreeModel({
			dataSource: new TestDataSource()
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('setInput, getInput', () => {
		model.setInput(SAMPLE.ONE);
		assert.equal(model.getInput(), SAMPLE.ONE);
	});

	test('refresh() refreshes all', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			counter.listen(model.onRefresh); // 1
			counter.listen(model.onDidRefresh); // 1
			counter.listen(model.onDidRefreshItem); // 4
			counter.listen(model.onRefreshItemChildren); // 1
			counter.listen(model.onDidRefreshItemChildren); // 1
			return model.refresh(null);
		}).then(() => {
			assert.equal(counter.count, 8);
		});
	});

	test('refresh(root) refreshes all', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			counter.listen(model.onRefresh); // 1
			counter.listen(model.onDidRefresh); // 1
			counter.listen(model.onDidRefreshItem); // 4
			counter.listen(model.onRefreshItemChildren); // 1
			counter.listen(model.onDidRefreshItemChildren); // 1
			return model.refresh(SAMPLE.AB);
		}).then(() => {
			assert.equal(counter.count, 8);
		});
	});

	test('refresh(root, false) refreshes the root', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			counter.listen(model.onRefresh); // 1
			counter.listen(model.onDidRefresh); // 1
			counter.listen(model.onDidRefreshItem); // 1
			counter.listen(model.onRefreshItemChildren); // 1
			counter.listen(model.onDidRefreshItemChildren); // 1
			return model.refresh(SAMPLE.AB, false);
		}).then(() => {
			assert.equal(counter.count, 5);
		});
	});

	test('refresh(collapsed element) does not refresh descendants', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			counter.listen(model.onRefresh); // 1
			counter.listen(model.onDidRefresh); // 1
			counter.listen(model.onDidRefreshItem); // 1
			counter.listen(model.onRefreshItemChildren); // 0
			counter.listen(model.onDidRefreshItemChildren); // 0
			return model.refresh(SAMPLE.AB.children[0]);
		}).then(() => {
			assert.equal(counter.count, 3);
		});
	});

	test('refresh(expanded element) refreshes the element and descendants', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand(SAMPLE.AB.children[0]).then(() => {
				counter.listen(model.onRefresh); // 1
				counter.listen(model.onDidRefresh); // 1
				counter.listen(model.onDidRefreshItem); // 3
				counter.listen(model.onRefreshItemChildren); // 1
				counter.listen(model.onDidRefreshItemChildren); // 1
				return model.refresh(SAMPLE.AB.children[0]);
			});
		}).then(() => {
			assert.equal(counter.count, 7);
		});
	});

	test('refresh(element, false) refreshes the element', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand(SAMPLE.AB.children[0]).then(() => {
				counter.listen(model.onRefresh); // 1
				counter.listen(model.onDidRefresh); // 1
				counter.listen(model.onDidRefreshItem, item => { // 1
					assert.equal(item.id, 'a');
					counter.up();
				});
				counter.listen(model.onRefreshItemChildren); // 1
				counter.listen(model.onDidRefreshItemChildren); // 1
				return model.refresh(SAMPLE.AB.children[0], false);
			});
		}).then(() => {
			assert.equal(counter.count, 6);
		});
	});

	test('depths', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll(['a', 'c']).then(() => {
				counter.listen(model.onDidRefreshItem, item => {
					switch (item.id) {
						case 'ROOT': assert.equal(item.getDepth(), 0); break;
						case 'a': assert.equal(item.getDepth(), 1); break;
						case 'aa': assert.equal(item.getDepth(), 2); break;
						case 'ab': assert.equal(item.getDepth(), 2); break;
						case 'b': assert.equal(item.getDepth(), 1); break;
						case 'c': assert.equal(item.getDepth(), 1); break;
						case 'ca': assert.equal(item.getDepth(), 2); break;
						case 'cb': assert.equal(item.getDepth(), 2); break;
						default: return;
					}
					counter.up();
				});

				return model.refresh();
			});
		}).then(() => {
			assert.equal(counter.count, 16);
		});
	});

	test('intersections', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll(['a', 'c']).then(() => {
				// going internals
				const r = (<any>model).registry;

				assert(r.getItem('a').intersects(r.getItem('a')));
				assert(r.getItem('a').intersects(r.getItem('aa')));
				assert(r.getItem('a').intersects(r.getItem('ab')));
				assert(r.getItem('aa').intersects(r.getItem('a')));
				assert(r.getItem('ab').intersects(r.getItem('a')));
				assert(!r.getItem('aa').intersects(r.getItem('ab')));
				assert(!r.getItem('a').intersects(r.getItem('b')));
				assert(!r.getItem('a').intersects(r.getItem('c')));
				assert(!r.getItem('a').intersects(r.getItem('ca')));
				assert(!r.getItem('aa').intersects(r.getItem('ca')));
			});
		});
	});
});

suite('TreeModel - TreeNavigator', () => {
	let model: model.TreeModel;
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
		model = new TreeModel({
			dataSource: new TestDataSource()
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('next()', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator();
			assert.equal(nav.next()!.id, 'a');
			assert.equal(nav.next()!.id, 'b');
			assert.equal(nav.next()!.id, 'c');
			assert.equal(nav.next() && false, null);
		});
	});

	test('previous()', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator();

			nav.next();
			nav.next();

			assert.equal(nav.next()!.id, 'c');
			assert.equal(nav.previous()!.id, 'b');
			assert.equal(nav.previous()!.id, 'a');
			assert.equal(nav.previous() && false, null);
		});
	});

	test('parent()', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator();

				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.parent()!.id, 'a');

				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.parent()!.id, 'a');

				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next()!.id, 'ca');
				assert.equal(nav.parent()!.id, 'c');

				assert.equal(nav.parent() && false, null);
			});
		});
	});

	test('next() - scoped', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator(SAMPLE.AB.children[0]);
			return model.expand({ id: 'a' }).then(() => {
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next() && false, null);
			});
		});
	});

	test('previous() - scoped', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator(SAMPLE.AB.children[0]);
			return model.expand({ id: 'a' }).then(() => {
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.previous()!.id, 'aa');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('parent() - scoped', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator(SAMPLE.AB.children[0]);

				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.parent() && false, null);
			});
		});
	});

	test('next() - non sub tree only', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator(SAMPLE.AB.children[0], false);
			return model.expand({ id: 'a' }).then(() => {
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next() && false, null);
			});
		});
	});

	test('previous() - non sub tree only', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator(SAMPLE.AB.children[0], false);
			return model.expand({ id: 'a' }).then(() => {
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.previous()!.id, 'b');
				assert.equal(nav.previous()!.id, 'ab');
				assert.equal(nav.previous()!.id, 'aa');
				assert.equal(nav.previous()!.id, 'a');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('parent() - non sub tree only', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator(SAMPLE.AB.children[0], false);

				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.parent()!.id, 'a');
				assert.equal(nav.parent() && false, null);
			});
		});
	});

	test('deep next() - scoped', () => {
		return model.setInput(SAMPLE.DEEP).then(() => {
			return model.expand(SAMPLE.DEEP.children[0]).then(() => {
				return model.expand(SAMPLE.DEEP.children[0].children[0]).then(() => {
					const nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]);
					assert.equal(nav.next()!.id, 'xa');
					assert.equal(nav.next()!.id, 'xb');
					assert.equal(nav.next() && false, null);
				});
			});
		});
	});

	test('deep previous() - scoped', () => {
		return model.setInput(SAMPLE.DEEP).then(() => {
			return model.expand(SAMPLE.DEEP.children[0]).then(() => {
				return model.expand(SAMPLE.DEEP.children[0].children[0]).then(() => {
					const nav = model.getNavigator(SAMPLE.DEEP.children[0].children[0]);
					assert.equal(nav.next()!.id, 'xa');
					assert.equal(nav.next()!.id, 'xb');
					assert.equal(nav.previous()!.id, 'xa');
					assert.equal(nav.previous() && false, null);
				});
			});
		});
	});

	test('last()', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator();
				assert.equal(nav.last()!.id, 'cb');
			});
		});
	});
});

suite('TreeModel - Expansion', () => {
	let model: model.TreeModel;
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
		model = new TreeModel({
			dataSource: new TestDataSource()
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('collapse, expand', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			counter.listen(model.onExpandItem, (e) => {
				assert.equal(e.item.id, 'a');
				const nav = model.getNavigator(e.item);
				assert.equal(nav.next() && false, null);
			});

			counter.listen(model.onDidExpandItem, (e) => {
				assert.equal(e.item.id, 'a');
				const nav = model.getNavigator(e.item);
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next() && false, null);
			});

			assert(!model.isExpanded(SAMPLE.AB.children[0]));

			let nav = model.getNavigator();
			assert.equal(nav.next()!.id, 'a');
			assert.equal(nav.next()!.id, 'b');
			assert.equal(nav.next()!.id, 'c');
			assert.equal(nav.next() && false, null);

			assert.equal(model.getExpandedElements().length, 0);

			return model.expand(SAMPLE.AB.children[0]).then(() => {
				assert(model.isExpanded(SAMPLE.AB.children[0]));

				nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next() && false, null);

				const expandedElements = model.getExpandedElements();
				assert.equal(expandedElements.length, 1);
				assert.equal(expandedElements[0].id, 'a');

				assert.equal(counter.count, 2);
			});
		});
	});

	test('toggleExpansion', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			assert(!model.isExpanded(SAMPLE.AB.children[0]));

			return model.toggleExpansion(SAMPLE.AB.children[0]).then(() => {
				assert(model.isExpanded(SAMPLE.AB.children[0]));
				assert(!model.isExpanded(SAMPLE.AB.children[0].children[0]));

				return model.toggleExpansion(SAMPLE.AB.children[0].children[0]).then(() => {
					assert(!model.isExpanded(SAMPLE.AB.children[0].children[0]));

					return model.toggleExpansion(SAMPLE.AB.children[0]).then(() => {
						assert(!model.isExpanded(SAMPLE.AB.children[0]));
					});
				});
			});
		});
	});

	test('collapseAll', () => {
		return model.setInput(SAMPLE.DEEP2).then(() => {
			return model.expand(SAMPLE.DEEP2.children[0]).then(() => {
				return model.expand(SAMPLE.DEEP2.children[0].children[0]).then(() => {

					assert(model.isExpanded(SAMPLE.DEEP2.children[0]));
					assert(model.isExpanded(SAMPLE.DEEP2.children[0].children[0]));

					return model.collapseAll().then(() => {
						assert(!model.isExpanded(SAMPLE.DEEP2.children[0]));

						return model.expand(SAMPLE.DEEP2.children[0]).then(() => {
							assert(!model.isExpanded(SAMPLE.DEEP2.children[0].children[0]));
						});
					});
				});
			});
		});
	});

	test('auto expand single child folders', () => {
		return model.setInput(SAMPLE.DEEP).then(() => {
			return model.expand(SAMPLE.DEEP.children[0]).then(() => {
				assert(model.isExpanded(SAMPLE.DEEP.children[0]));
				assert(model.isExpanded(SAMPLE.DEEP.children[0].children[0]));
			});
		});
	});

	test('expand can trigger refresh', () => {
		// MUnit.expect(16);
		return model.setInput(SAMPLE.AB).then(() => {

			assert(!model.isExpanded(SAMPLE.AB.children[0]));

			let nav = model.getNavigator();
			assert.equal(nav.next()!.id, 'a');
			assert.equal(nav.next()!.id, 'b');
			assert.equal(nav.next()!.id, 'c');
			assert.equal(nav.next() && false, null);

			const f: () => void = counter.listen(model.onRefreshItemChildren, (e) => {
				assert.equal(e.item.id, 'a');
				f();
			});

			const g: () => void = counter.listen(model.onDidRefreshItemChildren, (e) => {
				assert.equal(e.item.id, 'a');
				g();
			});

			return model.expand(SAMPLE.AB.children[0]).then(() => {
				assert(model.isExpanded(SAMPLE.AB.children[0]));

				nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next() && false, null);

				assert.equal(counter.count, 2);
			});
		});
	});

	test('top level collapsed', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			return model.collapseAll([{ id: 'a' }, { id: 'b' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.previous()!.id, 'b');
				assert.equal(nav.previous()!.id, 'a');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('shouldAutoexpand', () => {
		// setup
		const model = new TreeModel({
			dataSource: {
				getId: (_, e) => e,
				hasChildren: (_, e) => true,
				getChildren: (_, e) => {
					if (e === 'root') { return Promise.resolve(['a', 'b', 'c']); }
					if (e === 'b') { return Promise.resolve(['b1']); }
					return Promise.resolve([]);
				},
				getParent: (_, e): Promise<any> => { throw new Error('not implemented'); },
				shouldAutoexpand: (_, e) => e === 'b'
			}
		});

		return model.setInput('root').then(() => {
			return model.refresh('root', true);
		}).then(() => {
			assert(!model.isExpanded('a'));
			assert(model.isExpanded('b'));
			assert(!model.isExpanded('c'));
		});
	});
});

class TestFilter implements _.IFilter {

	public fn: (any) => boolean;

	constructor() {
		this.fn = () => true;
	}

	public isVisible(tree, element): boolean {
		return this.fn(element);
	}
}

suite('TreeModel - Filter', () => {
	let model: model.TreeModel;
	let counter: EventCounter;
	let filter: TestFilter;

	setup(() => {
		counter = new EventCounter();
		filter = new TestFilter();
		model = new TreeModel({
			dataSource: new TestDataSource(),
			filter: filter
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('no filter', () => {
		return model.setInput(SAMPLE.AB).then(() => {

			return model.expandAll([{ id: 'a' }, { id: 'c' }]).then(() => {
				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next()!.id, 'ca');
				assert.equal(nav.next()!.id, 'cb');

				assert.equal(nav.previous()!.id, 'ca');
				assert.equal(nav.previous()!.id, 'c');
				assert.equal(nav.previous()!.id, 'b');
				assert.equal(nav.previous()!.id, 'ab');
				assert.equal(nav.previous()!.id, 'aa');
				assert.equal(nav.previous()!.id, 'a');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('filter all', () => {
		filter.fn = () => false;

		return model.setInput(SAMPLE.AB).then(() => {
			return model.refresh().then(() => {
				const nav = model.getNavigator();
				assert.equal(nav.next() && false, null);
			});
		});
	});

	test('simple filter', () => {
		// hide elements that do not start with 'a'
		filter.fn = (e) => e.id[0] === 'a';

		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand({ id: 'a' }).then(() => {

				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'ab');
				assert.equal(nav.previous()!.id, 'aa');
				assert.equal(nav.previous()!.id, 'a');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('simple filter 2', () => {
		// hide 'ab'
		filter.fn = (e) => e.id !== 'ab';

		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand({ id: 'a' }).then(() => {
				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'a');
				assert.equal(nav.next()!.id, 'aa');
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next() && false, null);
			});
		});
	});

	test('simple filter, opposite', () => {
		// hide elements that start with 'a'
		filter.fn = (e) => e.id[0] !== 'a';

		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand({ id: 'c' }).then(() => {

				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next()!.id, 'ca');
				assert.equal(nav.next()!.id, 'cb');
				assert.equal(nav.previous()!.id, 'ca');
				assert.equal(nav.previous()!.id, 'c');
				assert.equal(nav.previous()!.id, 'b');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('simple filter, mischieving', () => {
		// hide the element 'a'
		filter.fn = (e) => e.id !== 'a';

		return model.setInput(SAMPLE.AB).then(() => {
			return model.expand({ id: 'c' }).then(() => {

				const nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'b');
				assert.equal(nav.next()!.id, 'c');
				assert.equal(nav.next()!.id, 'ca');
				assert.equal(nav.next()!.id, 'cb');
				assert.equal(nav.previous()!.id, 'ca');
				assert.equal(nav.previous()!.id, 'c');
				assert.equal(nav.previous()!.id, 'b');
				assert.equal(nav.previous() && false, null);
			});
		});
	});

	test('simple filter & previous', () => {
		// hide 'b'
		filter.fn = (e) => e.id !== 'b';

		return model.setInput(SAMPLE.AB).then(() => {
			const nav = model.getNavigator({ id: 'c' }, false);
			assert.equal(nav.previous()!.id, 'a');
			assert.equal(nav.previous() && false, null);
		});
	});
});

suite('TreeModel - Traits', () => {
	let model: model.TreeModel;
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
		model = new TreeModel({
			dataSource: new TestDataSource()
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('Selection', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			assert.equal(model.getSelection().length, 0);
			model.select(SAMPLE.AB.children[1]);
			assert(model.isSelected(SAMPLE.AB.children[1]));
			assert.equal(model.getSelection().length, 1);
			model.select(SAMPLE.AB.children[0]);
			assert(model.isSelected(SAMPLE.AB.children[0]));
			assert.equal(model.getSelection().length, 2);
			model.select(SAMPLE.AB.children[2]);
			assert(model.isSelected(SAMPLE.AB.children[2]));
			assert.equal(model.getSelection().length, 3);
			model.deselect(SAMPLE.AB.children[0]);
			assert(!model.isSelected(SAMPLE.AB.children[0]));
			assert.equal(model.getSelection().length, 2);
			model.setSelection([]);
			assert(!model.isSelected(SAMPLE.AB.children[0]));
			assert(!model.isSelected(SAMPLE.AB.children[1]));
			assert(!model.isSelected(SAMPLE.AB.children[2]));
			assert.equal(model.getSelection().length, 0);
			model.selectAll([SAMPLE.AB.children[0], SAMPLE.AB.children[1], SAMPLE.AB.children[2]]);
			assert.equal(model.getSelection().length, 3);
			model.select(SAMPLE.AB.children[0]);
			assert.equal(model.getSelection().length, 3);
			model.deselectAll([SAMPLE.AB.children[0], SAMPLE.AB.children[1], SAMPLE.AB.children[2]]);
			assert.equal(model.getSelection().length, 0);
			model.deselect(SAMPLE.AB.children[0]);
			assert.equal(model.getSelection().length, 0);

			model.setSelection([SAMPLE.AB.children[0]]);
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[0]));
			assert(!model.isSelected(SAMPLE.AB.children[1]));
			assert(!model.isSelected(SAMPLE.AB.children[2]));

			model.setSelection([SAMPLE.AB.children[0], SAMPLE.AB.children[1], SAMPLE.AB.children[2]]);
			assert.equal(model.getSelection().length, 3);
			assert(model.isSelected(SAMPLE.AB.children[0]));
			assert(model.isSelected(SAMPLE.AB.children[1]));
			assert(model.isSelected(SAMPLE.AB.children[2]));

			model.setSelection([SAMPLE.AB.children[1], SAMPLE.AB.children[2]]);
			assert.equal(model.getSelection().length, 2);
			assert(!model.isSelected(SAMPLE.AB.children[0]));
			assert(model.isSelected(SAMPLE.AB.children[1]));
			assert(model.isSelected(SAMPLE.AB.children[2]));

			model.setSelection([]);
			assert.deepEqual(model.getSelection(), []);
			assert.equal(model.getSelection().length, 0);
			assert(!model.isSelected(SAMPLE.AB.children[0]));
			assert(!model.isSelected(SAMPLE.AB.children[1]));
			assert(!model.isSelected(SAMPLE.AB.children[2]));

			model.selectNext();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[0]));

			model.selectNext();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[1]));

			model.selectNext();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[2]));

			model.selectNext();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[2]));

			model.selectPrevious();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[1]));

			model.selectPrevious();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[0]));

			model.selectPrevious();
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[0]));

			model.selectNext(2);
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[2]));

			model.selectPrevious(4);
			assert.equal(model.getSelection().length, 1);
			assert(model.isSelected(SAMPLE.AB.children[0]));

			assert.equal(model.isSelected(SAMPLE.AB.children[0]), true);
			assert.equal(model.isSelected(SAMPLE.AB.children[2]), false);
		});
	});

	test('Focus', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			assert(!model.getFocus());
			model.setFocus(SAMPLE.AB.children[1]);
			assert(model.isFocused(SAMPLE.AB.children[1]));
			assert(model.getFocus());
			model.setFocus(SAMPLE.AB.children[0]);
			assert(model.isFocused(SAMPLE.AB.children[0]));
			assert(model.getFocus());
			model.setFocus(SAMPLE.AB.children[2]);
			assert(model.isFocused(SAMPLE.AB.children[2]));
			assert(model.getFocus());
			model.setFocus();
			assert(!model.isFocused(SAMPLE.AB.children[0]));
			assert(!model.isFocused(SAMPLE.AB.children[1]));
			assert(!model.isFocused(SAMPLE.AB.children[2]));
			assert(!model.getFocus());

			model.setFocus(SAMPLE.AB.children[0]);
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[0]));
			assert(!model.isFocused(SAMPLE.AB.children[1]));
			assert(!model.isFocused(SAMPLE.AB.children[2]));

			model.setFocus();
			assert(!model.getFocus());
			assert(!model.isFocused(SAMPLE.AB.children[0]));
			assert(!model.isFocused(SAMPLE.AB.children[1]));
			assert(!model.isFocused(SAMPLE.AB.children[2]));

			model.focusNext();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[0]));

			model.focusNext();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[1]));

			model.focusNext();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[2]));

			model.focusNext();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[2]));

			model.focusPrevious();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[1]));

			model.focusPrevious();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[0]));

			model.focusPrevious();
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[0]));

			model.focusNext(2);
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[2]));

			model.focusPrevious(4);
			assert(model.getFocus());
			assert(model.isFocused(SAMPLE.AB.children[0]));

			assert.equal(model.isFocused(SAMPLE.AB.children[0]), true);
			assert.equal(model.isFocused(SAMPLE.AB.children[2]), false);

			model.focusFirst();
			assert(model.isFocused(SAMPLE.AB.children[0]));
			model.focusNth(0);
			assert(model.isFocused(SAMPLE.AB.children[0]));
			model.focusNth(1);
			assert(model.isFocused(SAMPLE.AB.children[1]));
		});
	});

	test('Highlight', () => {
		return model.setInput(SAMPLE.AB).then(() => {
			assert(!model.getHighlight());
			model.setHighlight(SAMPLE.AB.children[1]);
			assert(model.isHighlighted(SAMPLE.AB.children[1]));
			assert(model.getHighlight());
			model.setHighlight(SAMPLE.AB.children[0]);
			assert(model.isHighlighted(SAMPLE.AB.children[0]));
			assert(model.getHighlight());
			model.setHighlight(SAMPLE.AB.children[2]);
			assert(model.isHighlighted(SAMPLE.AB.children[2]));
			assert(model.getHighlight());
			model.setHighlight();
			assert(!model.isHighlighted(SAMPLE.AB.children[0]));
			assert(!model.isHighlighted(SAMPLE.AB.children[1]));
			assert(!model.isHighlighted(SAMPLE.AB.children[2]));
			assert(!model.getHighlight());

			model.setHighlight(SAMPLE.AB.children[0]);
			assert(model.getHighlight());
			assert(model.isHighlighted(SAMPLE.AB.children[0]));
			assert(!model.isHighlighted(SAMPLE.AB.children[1]));
			assert(!model.isHighlighted(SAMPLE.AB.children[2]));

			assert.equal(model.isHighlighted(SAMPLE.AB.children[0]), true);
			assert.equal(model.isHighlighted(SAMPLE.AB.children[2]), false);

			model.setHighlight();
			assert(!model.getHighlight());
			assert(!model.isHighlighted(SAMPLE.AB.children[0]));
			assert(!model.isHighlighted(SAMPLE.AB.children[1]));
			assert(!model.isHighlighted(SAMPLE.AB.children[2]));
		});
	});
});

class DynamicModel implements _.IDataSource {

	private data: any;
	public promiseFactory: { (): Promise<any>; } | null;

	private _onGetChildren = new Emitter<any>();
	readonly onGetChildren: Event<any> = this._onGetChildren.event;

	private _onDidGetChildren = new Emitter<any>();
	readonly onDidGetChildren: Event<any> = this._onDidGetChildren.event;

	constructor() {
		this.data = { root: [] };
		this.promiseFactory = null;
	}

	public addChild(parent, child): void {
		if (!this.data[parent]) {
			this.data[parent] = [];
		}
		this.data[parent].push(child);
	}

	public removeChild(parent, child): void {
		this.data[parent].splice(this.data[parent].indexOf(child), 1);
		if (this.data[parent].length === 0) {
			delete this.data[parent];
		}
	}

	public move(element, oldParent, newParent): void {
		this.removeChild(oldParent, element);
		this.addChild(newParent, element);
	}

	public rename(parent, oldName, newName): void {
		this.removeChild(parent, oldName);
		this.addChild(parent, newName);
	}

	public getId(tree, element): string {
		return element;
	}

	public hasChildren(tree, element): boolean {
		return !!this.data[element];
	}

	public getChildren(tree, element): Promise<any> {
		this._onGetChildren.fire(element);
		const result = this.promiseFactory ? this.promiseFactory() : Promise.resolve(null);
		return result.then(() => {
			this._onDidGetChildren.fire(element);
			return Promise.resolve(this.data[element]);
		});
	}

	public getParent(tree, element): Promise<any> {
		throw new Error('Not implemented');
	}
}

suite('TreeModel - Dynamic data model', () => {
	let model: model.TreeModel;
	let dataModel: DynamicModel;
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
		dataModel = new DynamicModel();
		model = new TreeModel({
			dataSource: dataModel,
		});
	});

	teardown(() => {
		counter.dispose();
		model.dispose();
	});

	test('items get property disposed', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');
		dataModel.addChild('father', 'daughter');
		dataModel.addChild('son', 'baby');

		return model.setInput('root').then(() => {
			return model.expandAll(['grandfather', 'father', 'son']).then(() => {
				dataModel.removeChild('grandfather', 'father');

				const items = ['baby', 'son', 'daughter', 'father'];
				let times = 0;
				counter.listen(model.onDidDisposeItem, item => {
					assert.equal(items[times++], item.id);
				});

				return model.refresh().then(() => {
					assert.equal(times, items.length);
					assert.equal(counter.count, 4);
				});
			});
		});
	});

	test('addChild, removeChild, collapse', () => {
		dataModel.addChild('root', 'super');
		dataModel.addChild('root', 'hyper');
		dataModel.addChild('root', 'mega');

		return model.setInput('root').then(() => {
			let nav = model.getNavigator();
			assert.equal(nav.next()!.id, 'super');
			assert.equal(nav.next()!.id, 'hyper');
			assert.equal(nav.next()!.id, 'mega');
			assert.equal(nav.next() && false, null);

			dataModel.removeChild('root', 'hyper');
			return model.refresh().then(() => {
				nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'super');
				assert.equal(nav.next()!.id, 'mega');
				assert.equal(nav.next() && false, null);

				dataModel.addChild('mega', 'micro');
				dataModel.addChild('mega', 'nano');
				dataModel.addChild('mega', 'pico');

				return model.refresh().then(() => {
					return model.expand('mega').then(() => {
						nav = model.getNavigator();
						assert.equal(nav.next()!.id, 'super');
						assert.equal(nav.next()!.id, 'mega');
						assert.equal(nav.next()!.id, 'micro');
						assert.equal(nav.next()!.id, 'nano');
						assert.equal(nav.next()!.id, 'pico');
						assert.equal(nav.next() && false, null);

						model.collapse('mega');
						nav = model.getNavigator();
						assert.equal(nav.next()!.id, 'super');
						assert.equal(nav.next()!.id, 'mega');
						assert.equal(nav.next() && false, null);
					});
				});
			});
		});
	});

	test('move', () => {
		dataModel.addChild('root', 'super');
		dataModel.addChild('super', 'apples');
		dataModel.addChild('super', 'bananas');
		dataModel.addChild('super', 'pears');
		dataModel.addChild('root', 'hyper');
		dataModel.addChild('root', 'mega');

		return model.setInput('root').then(() => {

			return model.expand('super').then(() => {

				let nav = model.getNavigator();
				assert.equal(nav.next()!.id, 'super');
				assert.equal(nav.next()!.id, 'apples');
				assert.equal(nav.next()!.id, 'bananas');
				assert.equal(nav.next()!.id, 'pears');
				assert.equal(nav.next()!.id, 'hyper');
				assert.equal(nav.next()!.id, 'mega');
				assert.equal(nav.next() && false, null);

				dataModel.move('bananas', 'super', 'hyper');
				dataModel.move('apples', 'super', 'mega');

				return model.refresh().then(() => {

					return model.expandAll(['hyper', 'mega']).then(() => {
						nav = model.getNavigator();
						assert.equal(nav.next()!.id, 'super');
						assert.equal(nav.next()!.id, 'pears');
						assert.equal(nav.next()!.id, 'hyper');
						assert.equal(nav.next()!.id, 'bananas');
						assert.equal(nav.next()!.id, 'mega');
						assert.equal(nav.next()!.id, 'apples');
						assert.equal(nav.next() && false, null);
					});
				});
			});
		});
	});

	test('refreshing grandfather recursively should not refresh collapsed father\'s children immediately', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.collapse('father').then(() => {
					let times = 0;
					let listener = dataModel.onGetChildren((element) => {
						times++;
						assert.equal(element, 'grandfather');
					});

					return model.refresh('grandfather').then(() => {
						assert.equal(times, 1);
						listener.dispose();

						listener = dataModel.onGetChildren((element) => {
							times++;
							assert.equal(element, 'father');
						});

						return model.expand('father').then(() => {
							assert.equal(times, 2);
							listener.dispose();
						});
					});
				});
			});
		});
	});

	test('simultaneously refreshing two disjoint elements should parallelize the refreshes', () => {
		dataModel.addChild('root', 'father');
		dataModel.addChild('root', 'mother');
		dataModel.addChild('father', 'son');
		dataModel.addChild('mother', 'daughter');

		return model.setInput('root').then(() => {
			return model.expand('father').then(() => {
				return model.expand('mother').then(() => {

					let nav = model.getNavigator();
					assert.equal(nav.next()!.id, 'father');
					assert.equal(nav.next()!.id, 'son');
					assert.equal(nav.next()!.id, 'mother');
					assert.equal(nav.next()!.id, 'daughter');
					assert.equal(nav.next() && false, null);

					dataModel.removeChild('father', 'son');
					dataModel.removeChild('mother', 'daughter');
					dataModel.addChild('father', 'brother');
					dataModel.addChild('mother', 'sister');

					dataModel.promiseFactory = () => { return timeout(0); };

					let getTimes = 0;
					let gotTimes = 0;
					const getListener = dataModel.onGetChildren((element) => { getTimes++; });
					const gotListener = dataModel.onDidGetChildren((element) => { gotTimes++; });

					const p1 = model.refresh('father');
					assert.equal(getTimes, 1);
					assert.equal(gotTimes, 0);

					const p2 = model.refresh('mother');
					assert.equal(getTimes, 2);
					assert.equal(gotTimes, 0);

					return Promise.all([p1, p2]).then(() => {
						assert.equal(getTimes, 2);
						assert.equal(gotTimes, 2);

						nav = model.getNavigator();
						assert.equal(nav.next()!.id, 'father');
						assert.equal(nav.next()!.id, 'brother');
						assert.equal(nav.next()!.id, 'mother');
						assert.equal(nav.next()!.id, 'sister');
						assert.equal(nav.next() && false, null);

						getListener.dispose();
						gotListener.dispose();
					});
				});
			});
		});
	});

	test('simultaneously recursively refreshing two intersecting elements should concatenate the refreshes - ancestor first', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.expand('father').then(() => {
					let nav = model.getNavigator();
					assert.equal(nav.next()!.id, 'grandfather');
					assert.equal(nav.next()!.id, 'father');
					assert.equal(nav.next()!.id, 'son');
					assert.equal(nav.next() && false, null);

					let refreshTimes = 0;
					counter.listen(model.onDidRefreshItem, (e) => { refreshTimes++; });

					let getTimes = 0;
					const getListener = dataModel.onGetChildren((element) => { getTimes++; });

					let gotTimes = 0;
					const gotListener = dataModel.onDidGetChildren((element) => { gotTimes++; });

					const p1Completes: Array<(value?: any) => void> = [];
					dataModel.promiseFactory = () => { return new Promise((c) => { p1Completes.push(c); }); };

					model.refresh('grandfather').then(() => {
						// just a single get
						assert.equal(refreshTimes, 1); // (+1) grandfather
						assert.equal(getTimes, 1);
						assert.equal(gotTimes, 0);

						// unblock the first get
						p1Completes.shift()!();

						// once the first get is unblocked, the second get should appear
						assert.equal(refreshTimes, 2); // (+1) first father refresh
						assert.equal(getTimes, 2);
						assert.equal(gotTimes, 1);

						let p2Complete;
						dataModel.promiseFactory = () => { return new Promise((c) => { p2Complete = c; }); };
						const p2 = model.refresh('father');

						// same situation still
						assert.equal(refreshTimes, 3); // (+1) second father refresh
						assert.equal(getTimes, 2);
						assert.equal(gotTimes, 1);

						// unblock the second get
						p1Completes.shift()!();

						// the third get should have appeared, it should've been waiting for the second one
						assert.equal(refreshTimes, 4); // (+1) first son request
						assert.equal(getTimes, 3);
						assert.equal(gotTimes, 2);

						p2Complete();

						// all good
						assert.equal(refreshTimes, 5); // (+1) second son request
						assert.equal(getTimes, 3);
						assert.equal(gotTimes, 3);

						return p2.then(() => {
							nav = model.getNavigator();
							assert.equal(nav.next()!.id, 'grandfather');
							assert.equal(nav.next()!.id, 'father');
							assert.equal(nav.next()!.id, 'son');
							assert.equal(nav.next() && false, null);

							getListener.dispose();
							gotListener.dispose();
						});
					});
				});
			});
		});
	});

	test('refreshing an empty element that adds children should still keep it collapsed', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.expand('father').then(() => {
					assert(!model.isExpanded('father'));

					dataModel.addChild('father', 'son');

					return model.refresh('father').then(() => {
						assert(!model.isExpanded('father'));
					});
				});
			});
		});
	});

	test('refreshing a collapsed element that adds children should still keep it collapsed', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.expand('father').then(() => {
					return model.collapse('father').then(() => {
						assert(!model.isExpanded('father'));

						dataModel.addChild('father', 'daughter');

						return model.refresh('father').then(() => {
							assert(!model.isExpanded('father'));
						});
					});
				});
			});
		});
	});

	test('recursively refreshing an ancestor of an expanded element, should keep that element expanded', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.expand('father').then(() => {
					assert(model.isExpanded('grandfather'));
					assert(model.isExpanded('father'));

					return model.refresh('grandfather').then(() => {
						assert(model.isExpanded('grandfather'));
						assert(model.isExpanded('father'));
					});
				});
			});
		});
	});

	test('recursively refreshing an ancestor of a collapsed element, should keep that element collapsed', () => {
		dataModel.addChild('root', 'grandfather');
		dataModel.addChild('grandfather', 'father');
		dataModel.addChild('father', 'son');

		return model.setInput('root').then(() => {
			return model.expand('grandfather').then(() => {
				return model.expand('father').then(() => {
					return model.collapse('father').then(() => {
						assert(model.isExpanded('grandfather'));
						assert(!model.isExpanded('father'));

						return model.refresh('grandfather').then(() => {
							assert(model.isExpanded('grandfather'));
							assert(!model.isExpanded('father'));
						});
					});
				});
			});
		});
	});

	test('Bug 10855:[explorer] quickly deleting things causes NPE in tree - intersectsLock should always be called when trying to unlock', () => {
		dataModel.addChild('root', 'father');
		dataModel.addChild('father', 'son');
		dataModel.addChild('root', 'mother');
		dataModel.addChild('mother', 'daughter');

		return model.setInput('root').then(() => {

			// delay expansions and refreshes
			dataModel.promiseFactory = () => { return timeout(0); };

			const promises: Promise<any>[] = [];

			promises.push(model.expand('father'));
			dataModel.removeChild('root', 'father');
			promises.push(model.refresh('root'));

			promises.push(model.expand('mother'));
			dataModel.removeChild('root', 'mother');
			promises.push(model.refresh('root'));

			return Promise.all(promises).then(() => {
				assert(true, 'all good');
			}, (errs) => {
				assert(false, 'should not fail');
			});
		});
	});
});

suite('TreeModel - bugs', () => {
	let counter: EventCounter;

	setup(() => {
		counter = new EventCounter();
	});

	teardown(() => {
		counter.dispose();
	});

	/**
	 * This bug occurs when an item is expanded right during its removal
	 */
	test('Bug 10566:[tree] build viewlet is broken after some time', () => {
		// setup
		let model = new TreeModel({
			dataSource: {
				getId: (_, e) => e,
				hasChildren: (_, e) => e === 'root' || e === 'bart',
				getChildren: (_, e) => {
					if (e === 'root') { return getRootChildren(); }
					if (e === 'bart') { return getBartChildren(); }
					return Promise.resolve([]);
				},
				getParent: (_, e): Promise<any> => { throw new Error('not implemented'); },
			}
		});

		let listeners = <any>[];

		// helpers
		const getGetRootChildren = (children: string[], millis = 0) => () => timeout(millis).then(() => children);
		let getRootChildren = getGetRootChildren(['homer', 'bart', 'lisa', 'marge', 'maggie'], 0);
		const getGetBartChildren = (millis = 0) => () => timeout(millis).then(() => ['milhouse', 'nelson']);
		const getBartChildren = getGetBartChildren(0);

		// item expanding should not exist!
		counter.listen(model.onExpandItem, () => { assert(false, 'should never receive item:expanding event'); });
		counter.listen(model.onDidExpandItem, () => { assert(false, 'should never receive item:expanded event'); });

		return model.setInput('root').then(() => {

			// remove bart
			getRootChildren = getGetRootChildren(['homer', 'lisa', 'marge', 'maggie'], 10);

			// refresh root
			const p1 = model.refresh('root', true).then(() => {
				assert(true);
			}, () => {
				assert(false, 'should never reach this');
			});

			// at the same time, try to expand bart!
			const p2 = model.expand('bart').then(() => {
				assert(false, 'should never reach this');
			}, () => {
				assert(true, 'bart should fail to expand since he was removed meanwhile');
			});

			// what now?
			return Promise.all([p1, p2]);

		}).then(() => {

			// teardown
			while (listeners.length > 0) { listeners.pop()(); }
			listeners = null;
			model.dispose();

			assert.equal(counter.count, 0);
		});
	});

	test('collapsed resolved parent should also update all children visibility on refresh', async function () {
		const counter = new EventCounter();
		const dataModel = new DynamicModel();

		let isSonVisible = true;
		const filter: _.IFilter = {
			isVisible(_, element) {
				return element !== 'son' || isSonVisible;
			}
		};

		const model = new TreeModel({ dataSource: dataModel, filter });

		dataModel.addChild('root', 'father');
		dataModel.addChild('father', 'son');

		await model.setInput('root');
		await model.expand('father');

		let nav = model.getNavigator();
		assert.equal(nav.next()!.id, 'father');
		assert.equal(nav.next()!.id, 'son');
		assert.equal(nav.next(), null);

		await model.collapse('father');
		isSonVisible = false;

		await model.refresh(undefined, true);
		await model.expand('father');

		nav = model.getNavigator();
		assert.equal(nav.next()!.id, 'father');
		assert.equal(nav.next(), null);

		counter.dispose();
		model.dispose();
	});
});


text:
<?php

namespace Vegas\Filesystem\Adapter\Exception\S3;

use Vegas\Filesystem\Exception as FilesystemException;

/**
 * Class InvalidCredentialsException
 * @package Vegas\Filesystem\Adapter\Exception
 */
class InvalidCredentialsException extends FilesystemException
{
    protected $message = 'Amazon S3 credentials are invalid';
}


text:
This example combines Code Splitting and Loaders. Make sure you have read the documentation of the examples that show the feature alone.

The bundle loader is used to create a wrapper module for `file.js` that loads this module on demand. The wrapper module returns a function that can be called to asynchronously receive the inner module.

# example.js

``` javascript
require("bundle!./file.js")(function(fileJsExports) {
	console.log(fileJsExports);
});
```

# file.js

``` javascript
module.exports = "It works";
```

# js/output.js

<details><summary>`/******/ (function(modules) { /* webpackBootstrap */ })`</summary>
``` javascript
/******/ (function(modules) { // webpackBootstrap
/******/ 	// install a JSONP callback for chunk loading
/******/ 	var parentJsonpFunction = window["webpackJsonp"];
/******/ 	window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
/******/ 		// add "moreModules" to the modules object,
/******/ 		// then flag all "chunkIds" as loaded and fire callback
/******/ 		var moduleId, chunkId, i = 0, resolves = [], result;
/******/ 		for(;i < chunkIds.length; i++) {
/******/ 			chunkId = chunkIds[i];
/******/ 			if(installedChunks[chunkId])
/******/ 				resolves.push(installedChunks[chunkId][0]);
/******/ 			installedChunks[chunkId] = 0;
/******/ 		}
/******/ 		for(moduleId in moreModules) {
/******/ 			if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ 				modules[moduleId] = moreModules[moduleId];
/******/ 			}
/******/ 		}
/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
/******/ 		while(resolves.length)
/******/ 			resolves.shift()();

/******/ 	};

/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// objects to store loaded and loading chunks
/******/ 	var installedChunks = {
/******/ 		1: 0
/******/ 	};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.l = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}

/******/ 	// This file contains only the entry chunk.
/******/ 	// The chunk loading function for additional chunks
/******/ 	__webpack_require__.e = function requireEnsure(chunkId) {
/******/ 		if(installedChunks[chunkId] === 0)
/******/ 			return Promise.resolve();

/******/ 		// an Promise means "currently loading".
/******/ 		if(installedChunks[chunkId]) {
/******/ 			return installedChunks[chunkId][2];
/******/ 		}
/******/ 		// start chunk loading
/******/ 		var head = document.getElementsByTagName('head')[0];
/******/ 		var script = document.createElement('script');
/******/ 		script.type = 'text/javascript';
/******/ 		script.charset = 'utf-8';
/******/ 		script.async = true;
/******/ 		script.timeout = 120000;

/******/ 		script.src = __webpack_require__.p + "" + chunkId + ".output.js";
/******/ 		var timeout = setTimeout(onScriptComplete, 120000);
/******/ 		script.onerror = script.onload = onScriptComplete;
/******/ 		function onScriptComplete() {
/******/ 			// avoid mem leaks in IE.
/******/ 			script.onerror = script.onload = null;
/******/ 			clearTimeout(timeout);
/******/ 			var chunk = installedChunks[chunkId];
/******/ 			if(chunk !== 0) {
/******/ 				if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
/******/ 				installedChunks[chunkId] = undefined;
/******/ 			}
/******/ 		};
/******/ 		head.appendChild(script);

/******/ 		var promise = new Promise(function(resolve, reject) {
/******/ 			installedChunks[chunkId] = [resolve, reject];
/******/ 		});
/******/ 		return installedChunks[chunkId][2] = promise;
/******/ 	};

/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// identity function for calling harmory imports with the correct context
/******/ 	__webpack_require__.i = function(value) { return value; };

/******/ 	// define getter function for harmory exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		Object.defineProperty(exports, name, {
/******/ 			configurable: false,
/******/ 			enumerable: true,
/******/ 			get: getter
/******/ 		});
/******/ 	};

/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};

/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "js/";

/******/ 	// on error function for async loading
/******/ 	__webpack_require__.oe = function(err) { console.error(err); throw err; };

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
```
</details>
``` javascript
/******/ ([
/* 0 */
/* unknown exports provided */
/* all exports used */
/*!*******************************************!*\
  !*** (webpack)/~/bundle-loader!./file.js ***!
  \*******************************************/
/***/ function(module, exports, __webpack_require__) {

var cbs = [],
	data;
module.exports = function(cb) {
	if(cbs) cbs.push(cb);
	else cb(data);
}
__webpack_require__.e/* nsure */(0).catch(function(err) { __webpack_require__.oe(err); }).then((function(require) {
	data = __webpack_require__(/*! !./file.js */ 2);
	var callbacks = cbs;
	cbs = null;
	for(var i = 0, l = callbacks.length; i < l; i++) {
		callbacks[i](data);
	}
}).bind(null, __webpack_require__));

/***/ },
/* 1 */
/* unknown exports provided */
/* all exports used */
/*!********************!*\
  !*** ./example.js ***!
  \********************/
/***/ function(module, exports, __webpack_require__) {

__webpack_require__(/*! bundle!./file.js */ 0)(function(fileJsExports) {
	console.log(fileJsExports);
});

/***/ }
/******/ ]);
```

# js/0.output.js

``` javascript
webpackJsonp([0],{

/***/ 2:
/* unknown exports provided */
/* all exports used */
/*!*****************!*\
  !*** ./file.js ***!
  \*****************/
/***/ function(module, exports) {

module.exports = "It works";

/***/ }

});
```

# Info

## Uncompressed

```
Hash: 4934f608e3c1f4ceb008
Version: webpack 2.1.0-beta.25
Time: 145ms
      Asset       Size  Chunks             Chunk Names
0.output.js  228 bytes       0  [emitted]
  output.js    6.24 kB       1  [emitted]  main
Entrypoint main = output.js
chunk    {0} 0.output.js 28 bytes {1} [rendered]
    > [0] (webpack)/~/bundle-loader!./file.js 7:0-14:2
    [2] ./file.js 28 bytes {0} [built]
        cjs require !!./file.js [0] (webpack)/~/bundle-loader!./file.js 8:8-30
chunk    {1} output.js (main) 367 bytes [entry] [rendered]
    > main [1] ./example.js
    [0] (webpack)/~/bundle-loader!./file.js 281 bytes {1} [built]
        cjs require bundle!./file.js [1] ./example.js 1:0-27
    [1] ./example.js 86 bytes {1} [built]
```

## Minimized (uglify-js, no zip)

```
Hash: 4934f608e3c1f4ceb008
Version: webpack 2.1.0-beta.25
Time: 304ms
      Asset      Size  Chunks             Chunk Names
0.output.js  58 bytes       0  [emitted]
  output.js   1.54 kB       1  [emitted]  main
Entrypoint main = output.js
chunk    {0} 0.output.js 28 bytes {1} [rendered]
    > [0] (webpack)/~/bundle-loader!./file.js 7:0-14:2
    [2] ./file.js 28 bytes {0} [built]
        cjs require !!./file.js [0] (webpack)/~/bundle-loader!./file.js 8:8-30
chunk    {1} output.js (main) 367 bytes [entry] [rendered]
    > main [1] ./example.js
    [0] (webpack)/~/bundle-loader!./file.js 281 bytes {1} [built]
        cjs require bundle!./file.js [1] ./example.js 1:0-27
    [1] ./example.js 86 bytes {1} [built]
```


text:
export interface BrowserNodeGlobal {
    Object: typeof Object;
    Array: typeof Array;
    Map: typeof Map;
    Set: typeof Set;
    Date: DateConstructor;
    RegExp: RegExpConstructor;
    JSON: typeof JSON;
    Math: any;
    assert(condition: any): void;
    Reflect: any;
    getAngularTestability: Function;
    getAllAngularTestabilities: Function;
    getAllAngularRootElements: Function;
    frameworkStabilizers: Array<Function>;
    setTimeout: Function;
    clearTimeout: Function;
    setInterval: Function;
    clearInterval: Function;
    encodeURI: Function;
}
export declare function scheduleMicroTask(fn: Function): void;
declare var _global: BrowserNodeGlobal;
export { _global as global };
export declare function getTypeNameForDebugging(type: any): string;
export declare function isPresent(obj: any): boolean;
export declare function isBlank(obj: any): boolean;
export declare function isBoolean(obj: any): boolean;
export declare function isNumber(obj: any): boolean;
export declare function isString(obj: any): obj is string;
export declare function isFunction(obj: any): boolean;
export declare function isType(obj: any): boolean;
export declare function isStringMap(obj: any): obj is Object;
export declare function isStrictStringMap(obj: any): boolean;
export declare function isArray(obj: any): boolean;
export declare function isDate(obj: any): obj is Date;
export declare function noop(): void;
export declare function stringify(token: any): string;
export declare class StringJoiner {
    parts: string[];
    constructor(parts?: string[]);
    add(part: string): void;
    toString(): string;
}
export declare class NumberWrapper {
    static toFixed(n: number, fractionDigits: number): string;
    static equal(a: number, b: number): boolean;
    static parseIntAutoRadix(text: string): number;
    static parseInt(text: string, radix: number): number;
    static NaN: number;
    static isNumeric(value: any): boolean;
    static isNaN(value: any): boolean;
    static isInteger(value: any): boolean;
}
export declare var RegExp: RegExpConstructor;
export declare class FunctionWrapper {
    static apply(fn: Function, posArgs: any): any;
    static bind(fn: Function, scope: any): Function;
}
export declare function looseIdentical(a: any, b: any): boolean;
export declare function getMapKey<T>(value: T): T;
export declare function normalizeBlank(obj: Object): any;
export declare function normalizeBool(obj: boolean): boolean;
export declare function isJsObject(o: any): boolean;
export declare function print(obj: Error | Object): void;
export declare function warn(obj: Error | Object): void;
export declare class Json {
    static parse(s: string): Object;
    static stringify(data: Object): string;
}
export declare function setValueOnPath(global: any, path: string, value: any): void;
export declare function getSymbolIterator(): string | symbol;
export declare function evalExpression(sourceUrl: string, expr: string, declarations: string, vars: {
    [key: string]: any;
}): any;
export declare function isPrimitive(obj: any): boolean;
export declare function hasConstructor(value: Object, type: any): boolean;
export declare function escape(s: string): string;
export declare function escapeRegExp(s: string): string;


text:
"""mut2read.py

Author -- Gundula Povysil
Contact -- povysil@bioinf.jku.at

Takes a tabular file with mutations and a BAM file as input and prints
all tags of reads that carry the mutation to a user specified output file.
Creates fastq file of reads of tags with mutation.

=======  ==========  =================  ================================
Version  Date        Author             Description
2.0.0    2020-10-30  Gundula Povysil    -
=======  ==========  =================  ================================

USAGE: python mut2read.py DCS_Mutations.tabular DCS.bam Aligned_Families.tabular Interesting_Reads.fastq tag_count_dict.json
"""

import argparse
import json
import os
import sys

import numpy as np
import pysam
from cyvcf2 import VCF

def make_argparser():
    parser = argparse.ArgumentParser(description='Takes a vcf file with mutations and a BAM file as input and prints all tags of reads that carry the mutation to a user specified output file and creates a fastq file of reads of tags with mutation.')
    parser.add_argument('--mutFile',
                        help='VCF file with DCS mutations.')
    parser.add_argument('--bamFile',
                        help='BAM file with aligned DCS reads.')
    parser.add_argument('--familiesFile',
                        help='TABULAR file with aligned families.')
    parser.add_argument('--outputFastq',
                        help='Output FASTQ file of reads with mutations.')
    parser.add_argument('--outputJson',
                        help='Output JSON file to store collected data.')
    return parser

def mut2read(argv):
    parser = make_argparser()
    args = parser.parse_args(argv[1:])

    file1 = args.mutFile
    file2 = args.bamFile
    file3 = args.familiesFile
    outfile = args.outputFastq
    json_file = args.outputJson

    if os.path.isfile(file1) is False:
        sys.exit("Error: Could not find '{}'".format(file1))

    if os.path.isfile(file2) is False:
        sys.exit("Error: Could not find '{}'".format(file2))

    if os.path.isfile(file3) is False:
        sys.exit("Error: Could not find '{}'".format(file3))

    # read dcs bam file
    bam = pysam.AlignmentFile(file2, "rb")

    # get tags
    tag_dict = {}
    cvrg_dict = {}

    for variant in VCF(file1):
        chrom = variant.CHROM
        stop_pos = variant.start
        chrom_stop_pos = str(chrom) + "#" + str(stop_pos)
        ref = variant.REF
        alt = variant.ALT[0]
        dcs_len = []
        if len(ref) == len(alt):
            for pileupcolumn in bam.pileup(chrom, stop_pos - 1, stop_pos + 1, max_depth=100000000):
                if pileupcolumn.reference_pos == stop_pos:
                    count_alt = 0
                    count_ref = 0
                    count_indel = 0
                    count_n = 0
                    count_other = 0
                    count_lowq = 0
                    print("unfiltered reads=", pileupcolumn.n, "filtered reads=", len(pileupcolumn.pileups),
                          "difference= ", len(pileupcolumn.pileups) - pileupcolumn.n)
                    for pileupread in pileupcolumn.pileups:
                        if not pileupread.is_del and not pileupread.is_refskip:
                            # query position is None if is_del or is_refskip is set.
                            nuc = pileupread.alignment.query_sequence[pileupread.query_position]
                            dcs_len.append(len(pileupread.alignment.query_sequence))
                            if nuc == alt:
                                count_alt += 1
                                tag = pileupread.alignment.query_name
                                if tag in tag_dict:
                                    tag_dict[tag][chrom_stop_pos] = alt
                                else:
                                    tag_dict[tag] = {}
                                    tag_dict[tag][chrom_stop_pos] = alt
                            elif nuc == ref:
                                count_ref += 1
                            elif nuc == "N":
                                count_n += 1
                            elif nuc == "lowQ":
                                count_lowq += 1
                            else:
                                count_other += 1
                        else:
                            count_indel += 1
                    dcs_median = np.median(np.array(dcs_len))
                    cvrg_dict[chrom_stop_pos] = (count_ref, count_alt, dcs_median)

                    print("coverage at pos %s = %s, ref = %s, alt = %s, other bases = %s, N = %s, indel = %s, low quality = %s, median length of DCS = %s\n" %
                          (pileupcolumn.pos, count_ref + count_alt, count_ref, count_alt, count_other, count_n,
                           count_indel, count_lowq, dcs_median))
        else:
            print("indels are currently not evaluated")
    bam.close()

    with open(json_file, "w") as f:
        json.dump((tag_dict, cvrg_dict), f)

    # create fastq from aligned reads
    with open(outfile, 'w') as out:
        with open(file3, 'r') as families:
            for line in families:
                line = line.rstrip('\n')
                splits = line.split('\t')
                tag = splits[0]

                if tag in tag_dict:
                    str1 = splits[4]
                    curr_seq = str1.replace("-", "")
                    str2 = splits[5]
                    curr_qual = str2.replace(" ", "")

                    out.write("@" + splits[0] + "." + splits[1] + "." + splits[2] + "\n")
                    out.write(curr_seq + "\n")
                    out.write("+" + "\n")
                    out.write(curr_qual + "\n")

if __name__ == '__main__':
    sys.exit(mut2read(sys.argv))


text:
All notable changes to this project will be documented in this file.

## 2.2.2 - 7/12/2016
### Changed/Fixed
- Time zone offset is now set automatically, based on new SERVER_TIMEZONE constant.  This should fix [issue #2](https://github.com/rothkj1022/phppickem/issues/2) and [issue #16](https://github.com/rothkj1022/phppickem/issues/16)
- Fixed [issue #17](https://github.com/rothkj1022/phppickem/issues/17)
- Fix to escape characters in comment subjects.

## 2.2.1 - 7/7/2016
### Changed
- Fixed for LA Rams

## 2.2.0 - 4/21/2016
### Changed
- Updated installer with 2016 schedule
- Transitioned changelog.txt to CHANGELOG.md based on [recommendations by olivierlacan](https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md)
- Attempting to adhere more strictly to [Semantic Versioning](http://semver.org/) from here on out.

### Removed
- Removed all old NFL schedule spreadsheets from docs folder

## 2.1.3 - 9/10/2015
### Changed
- Removed all page references to phpFreaksCrypto class and added global reference.

## 2.1.2 - 8/28/2015
### Fixed
- Fixed team code for Washington Redskins as reported by aharonhannan. Also updated Cleveland Browns and Pittsburgh Steelers logos.
- Fixed bug when adding new user as admin and rewrote buildSchedule.php for fetching schedule from nfl.com instead of espn.com.
- Fixed password reset issue reported by hollywood-canuck.

## 2.1.1 - 8/12/2015
### Fixed
- Fixed error caused by missing mcrypt

## 2.1.0 - 8/6/2015
### Changed
 - Updated installer with 2015 schedule

## 2.0.4 - 3/31/2015
### Fixed
- Fixed installer bugs reported by BrentNewland

## 2.0.3 - 11/24/2014
### Changed
- Rewrote Load Scores script to pull data from nfl.com instead of espn.
- Minor updates to entry form page.

## 2.0.2 - 10/10/2014
### Added
- Pages are now printer friendly

### Fixed
- Fixed IE9+ support (SVG & fonts)
- Fixed several visual and functional bugs

## 2.0.1 - 9/29/2014
### Fixed
- Fixed display of correct or incorrect pick choices on entry form

## 2.0.0 - 9/27/2014
### Changed
- Updated code to use mysqli instead of mysql
- Implemented new responsive design

## 1.0.11 - 9/1/2014
### Changed
 - Updated installer with 2014 schedule

## 1.0.10 - 8/26/2013
### Changed
 - Updated installer with 2013 schedule

## 1.0.9 - 9/2/2012
## Changed
- Updated installer with 2012 schedule

## 1.0.8 - 8/8/2011
- Updated phpmailer to 5.2
- Updated htmlpurifier to lite v 1.3.0
- Updated installer with 2011 schedule

## 1.0.7.1 - 9/19/2010
### Fixed
 - Fixed conflict with HTMLPurifier on scores page

## 1.0.7 - 9/15/2010
### Added
- Added config option for display of users' names/usernames (real names, usernames, or both)
- Added HTMLPurifier to prevent cross-site scripting attacks

## 1.0.6 - 9/3/2010
### Changed
- Changed results & standings pages to display usernames instead of full names

### Fixed
- Fixed clickable helmets for Internet Explorer (all versions)

## 1.0.5 - 8/13/2010
### Fixed
- Fixed signup page (did not work when register_globals is off)

## 1.0.4 - 8/4/2010
### Changed
- Updated CBRTE to latest version (3.12a)
- Updated jquery timepicker to latest version (0.2), fixes am/pm bug

### Fixed
- Fixed schedule update mysql error

## 1.0.3 - 4/21/2010
### Changed
- Updated auto score retrieval script for 2010
- Updated install script with 2010 NFL schedule

## 1.0.2 - 9/14/2009
### Fixed
- Fixed picks entry when after current week is closed but not all games are complete for the week.

## 1.0.1 - 9/11/2009
### Added
- Added username to body of password reset email

### Fixed
- Fixed load scores function
- Fixed bug with display of results

## 1.0.0 - 8/27/2009
- Initial Release

## 0.9.0 - 8/28/2008
- Beta Release


text:
package nl.utwente.viskell.haskell.type;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Haskell TypeClass with its instances and superclasses.
 */
public class TypeClass implements Comparable<TypeClass> {

    /**
     * An instance declaration
     */
    final static class Instance implements Comparable<Instance> {

        /**
         * The type constructor that identifies this instance.
         */
        private final TypeCon typecon;

        /**
         * The number of type arguments that needs to be constrained to make this instance valid
         * For Example: Eq a => Eq (Maybe a) is the instance Maybe#1, and (Show l, Show r) => Show (Either l r) is Either#2
         * Most Prelude instances are simple enough to not required sub-constraints, so this number will be often just 0.
         */
        private final int constrainedArgs;

        public Instance(TypeCon typecon, int constrainedArgs) {
            super();
            this.typecon = typecon;
            this.constrainedArgs = constrainedArgs;
        }

        @Override
        public String toString() {
            return this.typecon.toString() + "#" + this.constrainedArgs;
        }

        @Override
        public int compareTo(Instance other) {
            return this.typecon.getName().compareTo(other.typecon.getName());
        }

    }
    /**
     * The name of this type class.
     */
    private String name;

    /**
     * The instances of this type class.
     */
    private Set<Instance> instances;

    /**
     * The superclasses of this type class.
     */
    private Set<TypeClass> supers;

    /** The optional type constructor to use for the typeclass defaulting. */
    private Optional<TypeCon> defaultType;

    /**
     * @param name The name of this type class.
     * @param types The types that are a member of this type class.
     */
    public TypeClass(String name, TypeCon ... cons) {
        this.name = name;
        this.instances = new HashSet<>();
        this.supers = new HashSet<>();
        this.defaultType = Optional.empty();
        for (TypeCon tc : cons) {
            this.addInstance(tc, 0);
        }
    }

    /**
     * @return The name of this type class.
     */
    public final String getName() {
        return this.name;
    }

    /**
     * @param tc The type constructor to add to this class
     * @param constrainedArgs the number of type parameter that needs to be constrained to make the instance valid
     */
    public final void addInstance(TypeCon tc, int constrainedArgs) {
            this.instances.add(new Instance(tc, constrainedArgs));
    }

    public void setDefaultType(TypeCon defType) {
        this.defaultType = Optional.of(defType);
    }

    protected Optional<TypeCon> getDefaultType() {
        return this.defaultType;
    }

    /**
     * @return the super classes of this type class
     */
    protected Set<TypeClass> getSupers() {
        return this.supers;
    }

    /**
     * @param tc The super class that this class requires
     */
    public final void addSuperClass(TypeClass tc) {
        this.supers.add(tc);
        // Also transitively add all the superclasses of this superclass for easier simplification
        this.supers.addAll(tc.supers);
    }

    protected Set<TypeCon> allInstanceTypeCons() {
        return this.instances.stream().map(i -> i.typecon).collect(Collectors.toSet());
    }

    /**
     * @param type The type constructor to check.
     * @return Whether the given type constructor is in this type class.
     */
    public final boolean hasType(TypeCon type) {
        Instance inst = new Instance(type, 0);
        return this.instances.stream().anyMatch(i -> i.compareTo(inst) == 0);
    }

    /**
     * @param type The type constructor to check.
     * @return The number of constrained arguments the instance of this typecon in this class has, or -1 if not found.
     */
    public int lookupConstrainedArgs(TypeCon con) {
        for (Instance inst : this.instances) {
            if (inst.typecon.equals(con)) {
                return inst.constrainedArgs;
            }
        }

        return -1;
    }

    public final String toString() {
        return String.format("%s=>%s:%s", this.supers.stream().map(t ->t.getName()), this.name, this.instances.toString());
    }

    @Override
    public int compareTo(TypeClass other) {
        return this.getName().compareTo(other.getName());
    }

}


text:
import {Injectable } from 'angular2/angular2';

@Injectable()
export class ProjectConstants {

  private _defaultLanguage: string = "de";
  private _userLanguage: string;
  private _baseUrl: string = "http://localhost:8080/PmsSample/api";

  public get defaultLanguage(): string {
    return this._defaultLanguage;
  }

  public get userLanguage(): string {
    if (!this._userLanguage) {
      var lang: string = navigator.language.split('-')[0]; // use navigator lang if available
      lang = /(de|en)/gi.test(lang) ? lang : this._defaultLanguage;
      this._userLanguage = lang;
    }
    return this._userLanguage;
  }

  public get baseUrl(): string {
    return this._baseUrl;
  }
}


text:
package org.apache.accumulo.test.functional;

import static org.apache.accumulo.fate.util.UtilWaitThread.sleepUninterruptibly;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.accumulo.cluster.ClusterControl;
import org.apache.accumulo.core.Constants;
import org.apache.accumulo.core.client.Accumulo;
import org.apache.accumulo.core.client.AccumuloClient;
import org.apache.accumulo.core.clientImpl.ClientInfo;
import org.apache.accumulo.core.conf.ClientProperty;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.metadata.MetadataTable;
import org.apache.accumulo.fate.zookeeper.ServiceLock;
import org.apache.accumulo.fate.zookeeper.ZooCache;
import org.apache.accumulo.fate.zookeeper.ZooReader;
import org.apache.accumulo.fate.zookeeper.ZooUtil;
import org.apache.accumulo.harness.AccumuloClusterHarness;
import org.apache.accumulo.minicluster.ServerType;
import org.apache.accumulo.miniclusterImpl.MiniAccumuloConfigImpl;
import org.apache.accumulo.test.TestIngest;
import org.apache.accumulo.test.TestIngest.IngestParams;
import org.apache.accumulo.test.VerifyIngest;
import org.apache.accumulo.test.VerifyIngest.VerifyParams;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.RawLocalFileSystem;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RestartIT extends AccumuloClusterHarness {
  private static final Logger log = LoggerFactory.getLogger(RestartIT.class);

  @Override
  public int defaultTimeoutSeconds() {
    return 10 * 60;
  }

  @Override
  public void configureMiniCluster(MiniAccumuloConfigImpl cfg, Configuration hadoopCoreSite) {
    cfg.setClientProperty(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT, "15s");
    cfg.setProperty(Property.INSTANCE_ZK_TIMEOUT, "15s");
    cfg.setProperty(Property.GC_CYCLE_DELAY, "1s");
    cfg.setProperty(Property.GC_CYCLE_START, "1s");
    hadoopCoreSite.set("fs.file.impl", RawLocalFileSystem.class.getName());
  }

  private ExecutorService svc;

  @Before
  public void setup() {
    svc = Executors.newFixedThreadPool(1);
  }

  @After
  public void teardown() throws Exception {
    if (svc == null) {
      return;
    }

    if (!svc.isShutdown()) {
      svc.shutdown();
    }

    while (!svc.awaitTermination(10, TimeUnit.SECONDS)) {
      log.info("Waiting for threadpool to terminate");
    }
  }

  @Test
  public void restartManager() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      final String tableName = getUniqueNames(1)[0];
      c.tableOperations().create(tableName);
      final ClusterControl control = getCluster().getClusterControl();

      VerifyParams params = new VerifyParams(getClientProps(), tableName, 10_000);

      Future<Integer> ret = svc.submit(() -> {
        try {
          return control.exec(TestIngest.class, new String[] {"-c", cluster.getClientPropsPath(),
              "--rows", "" + params.rows, "--table", tableName});
        } catch (IOException e) {
          log.error("Error running TestIngest", e);
          return -1;
        }
      });

      control.stopAllServers(ServerType.MANAGER);
      control.startAllServers(ServerType.MANAGER);
      assertEquals(0, ret.get().intValue());
      VerifyIngest.verifyIngest(c, params);
    }
  }

  @Test
  public void restartManagerRecovery() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      String tableName = getUniqueNames(1)[0];
      c.tableOperations().create(tableName);
      VerifyParams params = new VerifyParams(getClientProps(), tableName, 10_000);
      TestIngest.ingest(c, params);
      ClusterControl control = getCluster().getClusterControl();

      // TODO implement a kill all too?
      // cluster.stop() would also stop ZooKeeper
      control.stopAllServers(ServerType.MANAGER);
      control.stopAllServers(ServerType.TABLET_SERVER);
      control.stopAllServers(ServerType.GARBAGE_COLLECTOR);
      control.stopAllServers(ServerType.MONITOR);

      ClientInfo info = ClientInfo.from(c.properties());
      ZooReader zreader = new ZooReader(info.getZooKeepers(), info.getZooKeepersSessionTimeOut());
      ZooCache zcache = new ZooCache(zreader, null);
      var zLockPath = ServiceLock
          .path(ZooUtil.getRoot(c.instanceOperations().getInstanceID()) + Constants.ZMANAGER_LOCK);
      byte[] managerLockData;
      do {
        managerLockData = ServiceLock.getLockData(zcache, zLockPath, null);
        if (managerLockData != null) {
          log.info("Manager lock is still held");
          Thread.sleep(1000);
        }
      } while (managerLockData != null);

      cluster.start();
      sleepUninterruptibly(5, TimeUnit.MILLISECONDS);
      control.stopAllServers(ServerType.MANAGER);

      managerLockData = new byte[0];
      do {
        managerLockData = ServiceLock.getLockData(zcache, zLockPath, null);
        if (managerLockData != null) {
          log.info("Manager lock is still held");
          Thread.sleep(1000);
        }
      } while (managerLockData != null);
      cluster.start();
      VerifyIngest.verifyIngest(c, params);
    }
  }

  @Test
  public void restartManagerSplit() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      final String tableName = getUniqueNames(1)[0];
      final ClusterControl control = getCluster().getClusterControl();
      c.tableOperations().create(tableName);
      c.tableOperations().setProperty(tableName, Property.TABLE_SPLIT_THRESHOLD.getKey(), "5K");

      VerifyParams params = new VerifyParams(getClientProps(), tableName, 10_000);

      Future<Integer> ret = svc.submit(() -> {
        try {
          return control.exec(TestIngest.class, new String[] {"-c", cluster.getClientPropsPath(),
              "--rows", "" + params.rows, "--table", tableName});
        } catch (Exception e) {
          log.error("Error running TestIngest", e);
          return -1;
        }
      });

      control.stopAllServers(ServerType.MANAGER);

      ClientInfo info = ClientInfo.from(c.properties());
      ZooReader zreader = new ZooReader(info.getZooKeepers(), info.getZooKeepersSessionTimeOut());
      ZooCache zcache = new ZooCache(zreader, null);
      var zLockPath = ServiceLock
          .path(ZooUtil.getRoot(c.instanceOperations().getInstanceID()) + Constants.ZMANAGER_LOCK);
      byte[] managerLockData;
      do {
        managerLockData = ServiceLock.getLockData(zcache, zLockPath, null);
        if (managerLockData != null) {
          log.info("Manager lock is still held");
          Thread.sleep(1000);
        }
      } while (managerLockData != null);

      cluster.start();
      assertEquals(0, ret.get().intValue());
      VerifyIngest.verifyIngest(c, params);
    }
  }

  @Test
  public void killedTabletServer() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      String tableName = getUniqueNames(1)[0];
      c.tableOperations().create(tableName);
      VerifyParams params = new VerifyParams(getClientProps(), tableName, 10_000);
      TestIngest.ingest(c, params);
      VerifyIngest.verifyIngest(c, params);
      cluster.getClusterControl().stopAllServers(ServerType.TABLET_SERVER);
      cluster.start();
      VerifyIngest.verifyIngest(c, params);
    }
  }

  @Test
  public void killedTabletServer2() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      final String[] names = getUniqueNames(2);
      final String tableName = names[0];
      final ClusterControl control = getCluster().getClusterControl();
      c.tableOperations().create(tableName);
      // Original test started and then stopped a GC. Not sure why it did this. The GC was
      // already running by default, and it would have nothing to do after only creating a table
      control.stopAllServers(ServerType.TABLET_SERVER);

      cluster.start();
      c.tableOperations().create(names[1]);
    }
  }

  @Test
  public void killedTabletServerDuringShutdown() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      String tableName = getUniqueNames(1)[0];
      c.tableOperations().create(tableName);
      IngestParams params = new IngestParams(getClientProps(), tableName, 10_000);
      TestIngest.ingest(c, params);
      try {
        getCluster().getClusterControl().stopAllServers(ServerType.TABLET_SERVER);
        getCluster().getClusterControl().adminStopAll();
      } finally {
        getCluster().start();
      }
    }
  }

  @Test
  public void shutdownDuringCompactingSplitting() throws Exception {
    try (AccumuloClient c = Accumulo.newClient().from(getClientProps()).build()) {
      String tableName = getUniqueNames(1)[0];
      VerifyParams params = new VerifyParams(getClientProps(), tableName, 10_000);
      c.tableOperations().create(tableName);
      c.tableOperations().setProperty(tableName, Property.TABLE_SPLIT_THRESHOLD.getKey(), "10K");
      String splitThreshold = null;
      for (Entry<String,String> entry : c.tableOperations().getProperties(tableName)) {
        if (entry.getKey().equals(Property.TABLE_SPLIT_THRESHOLD.getKey())) {
          splitThreshold = entry.getValue();
          break;
        }
      }
      assertNotNull(splitThreshold);
      try {
        c.tableOperations().setProperty(MetadataTable.NAME, Property.TABLE_SPLIT_THRESHOLD.getKey(),
            "20K");
        TestIngest.ingest(c, params);
        c.tableOperations().flush(tableName, null, null, false);
        VerifyIngest.verifyIngest(c, params);
        getCluster().stop();
      } finally {
        if (getClusterType() == ClusterType.STANDALONE) {
          getCluster().start();
          c.tableOperations().setProperty(MetadataTable.NAME,
              Property.TABLE_SPLIT_THRESHOLD.getKey(), splitThreshold);
        }
      }
    }
  }
}