text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.7"/>
<title>App Engine Python SDK: google.appengine.ext.mapreduce.records.RecordsReader Class Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>

<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="common.css" rel="stylesheet" type="text/css"/>

App Engine Python SDK
    v1.6.9 rev.445

The Python runtime is available as an experimental Preview feature.

google

appengine

ext

mapreduce

records

RecordsReader

Public Member Functions |
List of all members

google.appengine.ext.mapreduce.records.RecordsReader Class Reference

Inheritance diagram for google.appengine.ext.mapreduce.records.RecordsReader:

  <map id="google.appengine.ext.mapreduce.records.RecordsReader_map" name="google.appengine.ext.mapreduce.records.RecordsReader_map">
</map>

Public Member Functions

def 	__init__

def 	read

def 	__iter__

def 	tell

def 	seek

Detailed Description

A reader for records format.

Constructor & Destructor Documentation

          def google.appengine.ext.mapreduce.records.RecordsReader.__init__
          (

          self,

          reader

          )

Init.

Args:
  reader: a reader conforming to Python io.RawIOBase interface that
implements 'read', 'seek', and 'tell'.

Member Function Documentation

          def google.appengine.ext.mapreduce.records.RecordsReader.read
          (

          self	)

Reads record from current position in reader.

Returns:
  original bytes stored in a single record.

          def google.appengine.ext.mapreduce.records.RecordsReader.seek
          (

          self,

          args,

          kwargs

          )

Set the file's current position.

Arguments are passed directly to the underlying reader.

          def google.appengine.ext.mapreduce.records.RecordsReader.tell
          (

          self	)

Return file's current position.

The documentation for this class was generated from the following file:

code/googleappengine-read-only/python/google/appengine/ext/mapreduce/records.py

<address class="footer">
    Maintained by tzmartin
</address>


text:
const uuidv4 = require('uuid/v4')
const fs = require('fs-extra')
const path = require('path')
const ua = require('universal-analytics')

let uuid
let visitor
let page = '/influx-opcua-logger/' + require('../package.json').version
let appStart = new Date()
let metrics = 0

async function start (metricCount) {
  metrics = metricCount
  if (!visitor) {
    let clientID = await getInstanceUUID()
    visitor = ua('UA-81483531-4', clientID)
    visitor.pageview(page)
      .event('Application', 'Startup', '#metrics', metrics)
      .send()
    setInterval(_sendHeartbeat, 60 * 60 * 1000)
  }
}

async function _sendHeartbeat () {
  let elapsedSeconds = Math.round((new Date() - appStart) / 1000)
  if (!visitor) return
  visitor.pageview(page)
    .event('Application', 'Heartbeat', '#elapsedTime', elapsedSeconds)
    .send()
}

async function getInstanceUUID () {
  if (uuid) return uuid
  const dataPath = process.env.DATA_PATH || path.resolve(process.cwd(), 'data')
  const uuidFile = path.resolve(dataPath, '.instance-uuid')
  if (await fs.exists(uuidFile)) {
    let fileContents = (await fs.readFile(uuidFile)).toString()
    if (fileContents.length === 36) {
      uuid = fileContents
      return uuid
    }
  }
  uuid = uuidv4()
  await fs.writeFile(uuidFile, uuid)
  return uuid
}

module.exports = { start }

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Text;

using Amazon.Runtime;

namespace Amazon.S3.Model
{
    /// <summary>
    /// Returns information about the  ListParts response and response metadata.
    /// </summary>
    public class ListPartsResponse : AmazonWebServiceResponse
    {
        private string bucketName;
        private string key;
        private string uploadId;
        private Owner owner;
        private Initiator initiator;
        private S3StorageClass storageClass;
        private int? partNumberMarker;
        private int? nextPartNumberMarker;
        private int? maxParts;
        private bool? isTruncated;
        private List<PartDetail> parts = new List<PartDetail>();
        private DateTime? abortDate;
        private string abortRuleId;

        /// <summary>
        /// Name of the bucketName to which the multipart upload was initiated.
        ///
        /// </summary>
        public string BucketName
        {
            get { return this.bucketName; }
            set { this.bucketName = value; }
        }

        // Check to see if BucketName property is set
        internal bool IsSetBucketName()
        {
            return this.bucketName != null;
        }

        /// <summary>
        /// Object key for which the multipart upload was initiated.
        ///
        /// </summary>
        public string Key
        {
            get { return this.key; }
            set { this.key = value; }
        }

        // Check to see if Key property is set
        internal bool IsSetKey()
        {
            return this.key != null;
        }

        /// <summary>
        /// Upload ID identifying the multipart upload whose parts are being listed.
        ///
        /// </summary>
        public string UploadId
        {
            get { return this.uploadId; }
            set { this.uploadId = value; }
        }

        // Check to see if UploadId property is set
        internal bool IsSetUploadId()
        {
            return this.uploadId != null;
        }

        /// <summary>
        /// Part number after which listing begins.
        ///
        /// </summary>
        public int PartNumberMarker
        {
            get { return this.partNumberMarker ?? default(int); }
            set { this.partNumberMarker = value; }
        }

        // Check to see if PartNumberMarker property is set
        internal bool IsSetPartNumberMarker()
        {
            return this.partNumberMarker.HasValue;
        }

        /// <summary>
        /// When a list is truncated, this element specifies the last part in the list, as well as the value to use for the part-number-marker request
        /// parameter in a subsequent request.
        ///
        /// </summary>
        public int NextPartNumberMarker
        {
            get { return this.nextPartNumberMarker ?? default(int); }
            set { this.nextPartNumberMarker = value; }
        }

        // Check to see if NextPartNumberMarker property is set
        internal bool IsSetNextPartNumberMarker()
        {
            return this.nextPartNumberMarker.HasValue;
        }

        /// <summary>
        /// Maximum number of parts that were allowed in the response.
        ///
        /// </summary>
        public int MaxParts
        {
            get { return this.maxParts ?? default(int); }
            set { this.maxParts = value; }
        }

        // Check to see if MaxParts property is set
        internal bool IsSetMaxParts()
        {
            return this.maxParts.HasValue;
        }

        /// <summary>
        /// Indicates whether the returned list of parts is truncated.
        ///
        /// </summary>
        public bool IsTruncated
        {
            get { return this.isTruncated ?? default(bool); }
            set { this.isTruncated = value; }
        }

        // Check to see if IsTruncated property is set
        internal bool IsSetIsTruncated()
        {
            return this.isTruncated.HasValue;
        }

        /// <summary>
        /// Gets and sets the Parts property.
        /// <para>
        /// PartDetails is a container for elements related to a particular part. A response can contain
        /// zero or more Part elements.
        /// </para>
        /// </summary>
        public List<PartDetail> Parts
        {
            get { return this.parts; }
            set { this.parts = value; }
        }

        // Check to see if Parts property is set
        internal bool IsSetParts()
        {
            return this.parts.Count > 0;
        }

        /// <summary>
        /// Identifies who initiated the multipart upload.
        ///
        /// </summary>
        public Initiator Initiator
        {
            get { return this.initiator; }
            set { this.initiator = value; }
        }

        // Check to see if Initiator property is set
        internal bool IsSetInitiator()
        {
            return this.initiator != null;
        }

        /// <summary>
        /// Gets and sets the Owner property.
        /// </summary>
        public Owner Owner
        {
            get { return this.owner; }
            set { this.owner = value; }
        }

        // Check to see if Owner property is set
        internal bool IsSetOwner()
        {
            return this.owner != null;
        }

        /// <summary>
        /// The class of storage used to store the object.
        ///
        /// </summary>
        public string StorageClass
        {
            get { return this.storageClass; }
            set { this.storageClass = value; }
        }

        // Check to see if StorageClass property is set
        internal bool IsSetStorageClass()
        {
            return this.storageClass != null;
        }

        /// <summary>
        /// Date when multipart upload will become eligible for abort operation by lifecycle.
        /// </summary>
        public DateTime AbortDate
        {
            get { return this.abortDate.GetValueOrDefault(); }
            set { this.abortDate = value; }
        }

        // Check to see if AbortDate property is set
        internal bool IsSetAbortDate()
        {
            return this.abortDate.HasValue;
        }

        /// <summary>
        /// Id of the lifecycle rule that makes a multipart upload eligible for abort operation.
        /// </summary>
        public string AbortRuleId
        {
            get { return this.abortRuleId; }
            set { this.abortRuleId = value; }
        }

        // Check to see if AbortRuleId property is set
        internal bool IsSetAbortRuleId()
        {
            return this.abortRuleId != null;
        }
    }
}


text:
package testutil

import (
	"path"
	"testing"

	globlib "github.com/pachyderm/ohmyglob"

	"github.com/pachyderm/pachyderm/v2/src/internal/require"
)

func DebugFiles(t testing.TB, dataRepo string) (map[string]*globlib.Glob, []string) {
	expectedFiles := make(map[string]*globlib.Glob)
	// Record glob patterns for expected pachd files.
	for _, file := range []string{"version", "logs.txt", "logs-previous**", "goroutine", "heap"} {
		pattern := path.Join("pachd", "*", "pachd", file)
		g, err := globlib.Compile(pattern, '/')
		require.NoError(t, err)
		expectedFiles[pattern] = g
	}
	// Record glob patterns for expected source repo files.
	for _, file := range []string{"commits.json", "commits-chart**"} {
		pattern := path.Join("source-repos", dataRepo, file)
		g, err := globlib.Compile(pattern, '/')
		require.NoError(t, err)
		expectedFiles[pattern] = g
	}
	var pipelines []string
	for i := 0; i < 3; i++ {
		pipeline := UniqueString("TestDebug")
		pipelines = append(pipelines, pipeline)
		// Record glob patterns for expected pipeline files.
		for _, container := range []string{"user", "storage"} {
			for _, file := range []string{"logs.txt", "logs-previous**", "goroutine", "heap"} {
				pattern := path.Join("pipelines", pipeline, "pods", "*", container, file)
				g, err := globlib.Compile(pattern, '/')
				require.NoError(t, err)
				expectedFiles[pattern] = g
			}
		}
		for _, file := range []string{"spec.json", "commits.json", "jobs.json", "commits-chart**", "jobs-chart**"} {
			pattern := path.Join("pipelines", pipeline, file)
			g, err := globlib.Compile(pattern, '/')
			require.NoError(t, err)
			expectedFiles[pattern] = g
		}
	}
	for _, app := range []string{"etcd", "pg-bouncer"} {
		for _, file := range []string{"logs.txt", "logs-previous**"} {
			pattern := path.Join(app, "*", file)
			g, err := globlib.Compile(pattern, '/')
			require.NoError(t, err)
			expectedFiles[pattern] = g
		}
	}
	return expectedFiles, pipelines
}


text:
var polymerDefinition;

if (window.daElements == null) {
  window.daElements = {};
}

polymerDefinition = _.deepSafeExtend(window.daElements.listElem, {
  is: "da-crb-list",
  properties: {},

  /*
  activeCase:
    type: Object
  tickingCount:
    type: Number
    computed: '_tickingCount(cases)'
  unconvertedCount:
    type: Number
    computed: '_unconvertedCount(cases)'
   */
  created: function() {},
  ready: function() {
    window.daElements.listElem.ready.call(this);
    this.push("filters", new window.daElements.daCaseFilter({
      properties: {
        name: "All Ticking Cases",
        ticking: true
      }
    }));
    this.push("filters", new window.daElements.daCaseFilter({
      properties: {
        name: "Converted Ticking Cases",
        ticking: true,
        custom: [
          function(caseEntry) {
            if (caseEntry.crb !== "need" && caseEntry.crb !== "reqd") {
              return true;
            }
            return false;
          }
        ]
      }
    }));
    this.push("filters", new window.daElements.daCaseFilter({
      properties: {
        name: "CRB Requested",
        ticking: true,
        custom: [
          function(caseEntry) {
            if (caseEntry.crb === "reqd") {
              return true;
            }
            return false;
          }
        ]
      }
    }));
    this.push("filters", new window.daElements.daCaseFilter({
      properties: {
        name: "CRB Needed",
        ticking: true,
        custom: [
          function(caseEntry) {
            if (caseEntry.crb === "need") {
              return true;
            }
            return false;
          }
        ]
      }
    }));
    this.activeFilterId = 0;
    return this.refresh();
  },
  load: function() {},
  cellTap: function(e) {
    switch (e.detail.column.header) {
      case "Docket":
        return this.docketTap(e);
    }
  },
  docketTap: function(e) {
    return app.displayCase(e.detail.item.id);
  },
  _convertCrbStatus: function(status) {
    if (status === "need") {
      return "Needed";
    }
    if (status === "reqd") {
      return "Requested";
    }
    if (status === "na" || status === "have") {
      return "C=I";
    }
    return "Unknown";
  },
  _unconvertedCount: function(cases) {
    var unconverted;
    unconverted = _.filter(cases, function(caseEntry) {
      if (caseEntry.crb === "need" || caseEntry.crb === "reqd") {
        return true;
      }
      return false;
    });
    return unconverted.length;
  },
  _tickingCount: function(cases) {
    var ticking;
    ticking = _.filter(cases, (function(_this) {
      return function(caseEntry) {
        return caseEntry.ticking;
      };
    })(this));
    return ticking.length;
  }
});

window.daElements.daCrbList = Polymer(polymerDefinition);


text:
<?php

/**
 * Array renderer for PHP_CompatInfo component.
 *
 * The PHP_CompatInfo_Renderer_Array class is a concrete implementation
 * of PHP_CompatInfo_Renderer abstract class. It simply display results as
 * a PHP array.
 *
 * @category PHP
 * @package  PHP_CompatInfo
 * @author   Laurent Laville <pear@laurent-laville.org>
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD
 * @version  Release: 1.8.1
 * @link     http://pear.php.net/package/PHP_CompatInfo
 * @since    Class available since Release 1.8.0b2
 */
class PHP_CompatInfo_Renderer_Array extends PHP_CompatInfo_Renderer
{
    /**
     * Driver to display results array.
     *
     * Default is PHP::var_export, but you can use PEAR::Var_Dump if available
     *
     * @var    string
     * @access public
     */
    var $driver;

    /**
     * Array Renderer Class constructor (ZE1) for PHP4
     *
     * @param object &$parser Instance of the parser (model of MVC pattern)
     * @param array  $conf    A hash containing any additional configuration
     *
     * @access public
     * @since  version 1.8.0b2 (2008-06-03)
     */
    function PHP_CompatInfo_Renderer_Array(&$parser, $conf)
    {
        $this->__construct($parser, $conf);
    }

    /**
     * Array Renderer Class constructor (ZE2) for PHP5+
     *
     * @param object &$parser Instance of the parser (model of MVC pattern)
     * @param array  $conf    A hash containing any additional configuration
     *
     * @access public
     * @since  version 1.8.0b2 (2008-06-03)
     */
    function __construct(&$parser, $conf)
    {
        parent::PHP_CompatInfo_Renderer($parser, $conf);

        $driver = 'PEAR::Var_Dump';

        if (isset($conf[$driver])) {
            $var_dump = 'Var_Dump.php';
            if (PHP_CompatInfo_Renderer::isIncludable($var_dump)) {
                include_once $var_dump;

                $class_options = $conf['PEAR::Var_Dump'];
                if (isset($class_options['options'])) {
                    $options = $class_options['options'];
                } else {
                    $options = array();
                }
                if (isset($class_options['rendererOptions'])) {
                    $rendererOptions = $class_options['rendererOptions'];
                } else {
                    $rendererOptions = array();
                }
                if (php_sapi_name() == 'cli') {
                    // prevent wrong display on command line interface
                    $options['display_mode'] = 'Text';
                }

                Var_Dump::displayInit($options, $rendererOptions);
                $this->driver = $driver;
            }
        }

        if (!isset($this->driver)) {
            // if optional driver not defined, then use default PHP::var_export
            $this->driver = 'PHP';
        }
    }

    /**
     * Display final results
     *
     * Display final results, when data source parsing is over.
     *
     * @access public
     * @return void
     * @since  version 1.8.0b2 (2008-06-03)
     */
    function display()
    {
        $o    = $this->args['output-level'];
        $v    = $this->args['verbose'];
        $data = $this->parseData;
        $src  = $this->_parser->dataSource;

        if ($data === false) {
            // invalid data source
            if ($this->driver == 'PHP') {
                var_export($data);
            } else {
                Var_Dump::display($data);
            }
            return;
        }

        $options = $this->_parser->options;

        if (isset($this->args['dir'])) {
            $files = $this->_parser->getFilelist($this->args['dir'], $options);
        } elseif (isset($this->args['file'])) {
            $files = array($this->args['file']);
        } elseif ($src['dataType'] == 'directory') {
            $files = $src['dataSource'];
        } elseif ($src['dataType'] == 'file') {
            $files = array($src['dataSource']);
        } else {
            $files = $src['dataSource'];
        }

        if ($options['is_string'] == true) {
            foreach ($files as $k => $str) {
                $files[$k] = 'string_' . ($k+1);
            }
        }

        if ($o & 16) {
            // display Version
        } else {
            unset($data['version'], $data['max_version']);
        }
        if ($o & 1) {
            // display Conditions
        } else {
            unset($data['cond_code']);
        }
        if ($o & 2) {
            // display Extensions
        } else {
            unset($data['extensions']);
        }
        if ($o & 4) {
            if ($o & 8) {
                // display Constants/Tokens
            } else {
                // display Constants
                unset($data['tokens']);
            }
        } else {
            unset($data['constants']);
            if ($o & 8) {
                // display Tokens
            } else {
                unset($data['tokens']);
            }
        }
        if ($v & 4 || $options['debug'] == true) {
            // display Functions
        } else {
            unset($data['functions']);
        }

        if (count($files) > 1) {
            if ($this->args['summarize'] === true) {
                foreach ($files as $file) {
                    unset($data[$file]);
                }
            } else {
                foreach ($files as $file) {
                    if ($o & 16) {
                        // display Version
                    } else {
                        unset($data[$file]['version'], $data[$file]['max_version']);
                    }
                    if ($o & 1) {
                        // display Conditions
                    } else {
                        unset($data[$file]['cond_code']);
                    }
                    if ($o & 2) {
                        // display Extensions
                    } else {
                        unset($data[$file]['extensions']);
                    }
                    if ($o & 4) {
                        if ($o & 8) {
                            // display Constants/Tokens
                        } else {
                            // display Constants
                            unset($data[$file]['tokens']);
                        }
                    } else {
                        unset($data[$file]['constants']);
                        if ($o & 8) {
                            // display Tokens
                        } else {
                            unset($data[$file]['tokens']);
                        }
                    }
                    if ($v & 4 || $options['debug'] == true) {
                        // display Functions
                    } else {
                        unset($data[$file]['functions']);
                    }
                }
            }
        }

        if ($this->driver == 'PHP') {
            var_export($data);
        } else {
            Var_Dump::display($data);
        }
    }
}
?>


text:
package mx.itam.metodos.tools;

import java.io.IOException;
import java.util.List;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import com.google.common.base.Joiner;
import com.google.common.collect.Lists;

public class GroupReducer extends Reducer<Text, Text, Text, Text> {

  @Override
  public void reduce(Text key, Iterable<Text> values, Context ctx)
    throws IOException, InterruptedException {
    List<String> data = Lists.newArrayList();
    for (Text x : values) {
     data.add(x.toString());
    }
    Joiner joiner = Joiner.on(" ");
    ctx.write(key, new Text(joiner.join(data)));
  }
}


text:
games-api
=========

REST API for handling games and moves


text:
String.prototype.ltrim = function() {
    return this.replace(/^\s+/,"");
};
String.prototype.rtrim = function() {
    return this.replace(/\s+$/,"");
};

$("input:submit").button();


text:
* [modules](modules) - Example of free-floating .md files - includes docs/modules/behaviors/DATA_BEHAVIOR.md
* [Generated API](api) - Generated using jsdoc against 3 files (View.js, Behavior.js, torso.js) - will take some work to generate the rest of the files.
  * [Generated API in markdown](apimd/API.md) - jsdoc generated same as above and then converted to markdown (for native github access).
* [Annotated Source](ANNOTATED.md) - ToC to docs generated using docco (same as Backbone annotated source)
* [Interactive docs](interactive) - Old Github Pages code from gh-pages branch.

## Existing .md documation links

* [API](API.md) - From docs/API.md
* [DEVELOPMENT](DEVELOPMENT.md) - From docs/DEVELOPMENT.md
* [DOCUMENTATION](DOCUMENTATION.md) - From docs/DOCUMENTATION.md
* [RULES](RULES.md) - From docs/RULES.md


text:
div {
     background-color: green !important;
}


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

## [Unreleased]

## [3.1.0]
### Changed
- Bump nokogiri version (#302)
- Fix auto-link emoji parsing (#304)
- Updates known gTLDs to recognize recent additions by IANA (#308)
- Fix warning about has_rdoc usage (#309)

## [3.0.0]
### Added
- New v3.json config file with emojiParsingEnabled config option. When
  true, twitter-text will parse and discount emoji supported by the
  twemoji library (see https://github.com/twitter/twemoji). The length
  of these emoji will be the default weight (200 or two characters) even
  if they contain multiple code points combined by zero-width
  joiners. This means that emoji with skin tone and gender modifiers no
  longer count as more characters than those without such modifiers.
### Changed
- Updates known gTLDs to recognize recent additions by IANA (#261)

## [2.1] - 2017-12-20
### Added
- This CHANGELOG.md file

### Changed
- Top-level namespace changed from `Twitter` to `Twitter::TwitterText`. This
  resolves a namespace collision with the popular
  [twitter gem](https://github.com/sferik/twitter). This is considered
  a breaking change, so the version has been bumped to 2.1. This fixes
  issue [#221](https://github.com/twitter/twitter-text/issues/221),
  "NoMethodError Exception: undefined method `[]' for nil:NilClasswhen
  using gem in rails app"

## [2.0.2] - 2017-12-18
### Changed
- Resolved issue
  [#211](https://github.com/twitter/twitter-text/issues/211), "gem
  breaks, asset file is a dangling symlink"
- config files, tld_lib.yml files now copied into the right place
- Rakefile now included `prebuild`, `clean` tasks


text:
package com.outbrain.ob1k.cache;

import com.outbrain.ob1k.concurrent.ComposableFuture;

import java.util.Map;

/**
 * Created by aronen on 8/27/14.
 *
 * an interface for local async cache with loader.
 */
public interface TypedCache<K, V> {
    ComposableFuture<V> getAsync(final K key);
    ComposableFuture<Map<K, V>> getBulkAsync(final Iterable<? extends K> keys);

    ComposableFuture<Boolean> setAsync(final K key, final  V value);
    ComposableFuture<Boolean> setAsync(final K key, final EntryMapper<K, V> mapper, final int maxIterations);
    ComposableFuture<Map<K, Boolean>> setBulkAsync(final Map<? extends K, ? extends V> entries);

    ComposableFuture<Boolean> deleteAsync(final K key);
}


text:
package com.sleepycat.persist;

import com.sleepycat.db.DatabaseException;

/**
 * Thrown by the {@link EntityStore} constructor when the {@link
 * StoreConfig#setAllowCreate AllowCreate} configuration parameter is false and
 * the store's internal catalog database does not exist.
 *
 * @author Mark Hayes
 */
public class StoreNotFoundException extends DatabaseException {

    private static final long serialVersionUID = 1895430616L;

    public StoreNotFoundException(String message) {
        super(message);
    }
}


text:
package accountstatus

import (
	"encoding/json"
	"fmt"
	"reflect"
)

// Enum is an enumerated type
type Enum uint8

const (
	// Pending is an enumeration for accountstatus.Enum
	Pending Enum = iota + 1
	// Active is an enumeration for accountstatus.Enum
	Active
	// Overdue is an enumeration for accountstatus.Enum
	Overdue
	// Warning is an enumeration for accountstatus.Enum
	Warning
	// Suspended is an enumeration for accountstatus.Enum
	Suspended
	// Terminated is an enumeration for accountstatus.Enum
	Terminated
	// Closed is an enumeration for accountstatus.Enum
	Closed
	// Deleted is an enumeration for accountstatus.Enum
	Deleted
)

// ValidStrings is the set of strings that are valid inputs to ParseEnum
var ValidStrings = []string{
	Pending.String(),
	Active.String(),
	Overdue.String(),
	Warning.String(),
	Suspended.String(),
	Terminated.String(),
	Closed.String(),
	Deleted.String(),
}

// String makes Enum satisfy the Stringer interface
func (i Enum) String() string {
	tmp, err := i.MarshalText()
	if err == nil {
		return string(tmp)
	}
	return ""
}

// ParseEnum attempts to convert a string into a Enum
func ParseEnum(name string) (Enum, error) {
	switch name {
	case "pending":
		return Pending, nil
	case "active":
		return Active, nil
	case "overdue":
		return Overdue, nil
	case "warning":
		return Warning, nil
	case "suspended":
		return Suspended, nil
	case "terminated":
		return Terminated, nil
	case "closed":
		return Closed, nil
	case "deleted":
		return Deleted, nil
	}
	var zero Enum
	return zero, fmt.Errorf("%s is not a valid accountstatus.Enum", name)
}

// MarshalText implements the text marshaller method
func (i Enum) MarshalText() ([]byte, error) {
	switch i {
	case Pending:
		return []byte("pending"), nil
	case Active:
		return []byte("active"), nil
	case Overdue:
		return []byte("overdue"), nil
	case Warning:
		return []byte("warning"), nil
	case Suspended:
		return []byte("suspended"), nil
	case Terminated:
		return []byte("terminated"), nil
	case Closed:
		return []byte("closed"), nil
	case Deleted:
		return []byte("deleted"), nil
	}
	return nil, fmt.Errorf("%d is not a valid accountstatus.Enum", i)
}

// UnmarshalText implements the text unmarshaller method
func (i *Enum) UnmarshalText(text []byte) error {
	name := string(text)
	tmp, err := ParseEnum(name)
	if err != nil {
		return &json.UnmarshalTypeError{
			Value: name,
			Type:  reflect.TypeOf(*i),
		}
	}
	*i = tmp
	return nil
}


text:
#include "config.h"
#include "WebWorkerClientImpl.h"

#if ENABLE(WORKERS)

#include "CrossThreadTask.h"
#include "DedicatedWorkerThread.h"
#include "ErrorEvent.h"
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "MessageEvent.h"
#include "MessagePort.h"
#include "MessagePortChannel.h"
#include "ScriptCallStack.h"
#include "ScriptExecutionContext.h"
#include "Worker.h"
#include "WorkerContext.h"
#include "WorkerContextExecutionProxy.h"
#include "WorkerScriptController.h"
#include "WorkerMessagingProxy.h"
#include <wtf/Threading.h>

#include "FrameLoaderClientImpl.h"
#include "PlatformMessagePortChannel.h"
#include "WebFrameClient.h"
#include "WebFrameImpl.h"
#include "WebKit.h"
#include "WebKitClient.h"
#include "WebMessagePortChannel.h"
#include "WebString.h"
#include "WebURL.h"
#include "WebViewImpl.h"
#include "WebWorker.h"
#include "WebWorkerImpl.h"

using namespace WebCore;

namespace WebKit {

// When WebKit creates a WorkerContextProxy object, we check if we're in the
// renderer or worker process.  If the latter, then we just use
// WorkerMessagingProxy.
//
// If we're in the renderer process, then we need use the glue provided
// WebWorker object to talk to the worker process over IPC.  The worker process
// talks to Worker* using WorkerObjectProxy, which we implement on
// WebWorkerClientImpl.
//
// Note that if we're running each worker in a separate process, then nested
// workers end up using the same codepath as the renderer process.

// static
WorkerContextProxy* WebWorkerClientImpl::createWorkerContextProxy(Worker* worker)
{
    // Special behavior for multiple workers per process.
    // FIXME: v8 doesn't support more than one workers per process.
    // if (!worker->scriptExecutionContext()->isDocument())
    //     return new WorkerMessagingProxy(worker);

    WebWorker* webWorker = 0;
    WebWorkerClientImpl* proxy = new WebWorkerClientImpl(worker);

    if (worker->scriptExecutionContext()->isDocument()) {
        Document* document = static_cast<Document*>(
            worker->scriptExecutionContext());
        WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame());
        webWorker = webFrame->client()->createWorker(webFrame, proxy);
    } else {
        WorkerScriptController* controller = WorkerScriptController::controllerForContext();
        if (!controller) {
            ASSERT_NOT_REACHED();
            return 0;
        }

        DedicatedWorkerThread* thread = static_cast<DedicatedWorkerThread*>(controller->workerContext()->thread());
        WorkerObjectProxy* workerObjectProxy = &thread->workerObjectProxy();
        WebWorkerImpl* impl = reinterpret_cast<WebWorkerImpl*>(workerObjectProxy);
        webWorker = impl->client()->createWorker(proxy);
    }

    proxy->setWebWorker(webWorker);
    return proxy;
}

WebWorkerClientImpl::WebWorkerClientImpl(Worker* worker)
    : m_scriptExecutionContext(worker->scriptExecutionContext())
    , m_worker(worker)
    , m_askedToTerminate(false)
    , m_unconfirmedMessageCount(0)
    , m_workerContextHadPendingActivity(false)
    , m_workerThreadId(currentThread())
{
}

WebWorkerClientImpl::~WebWorkerClientImpl()
{
}

void WebWorkerClientImpl::setWebWorker(WebWorker* webWorker)
{
    m_webWorker = webWorker;
}

void WebWorkerClientImpl::startWorkerContext(const KURL& scriptURL,
                                             const String& userAgent,
                                             const String& sourceCode)
{
    // Worker.terminate() could be called from JS before the context is started.
    if (m_askedToTerminate)
        return;
    if (!isMainThread()) {
        WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(
            &startWorkerContextTask,
            this,
            scriptURL.string(),
            userAgent,
            sourceCode));
        return;
    }
    m_webWorker->startWorkerContext(scriptURL, userAgent, sourceCode);
}

void WebWorkerClientImpl::terminateWorkerContext()
{
    if (m_askedToTerminate)
        return;
    m_askedToTerminate = true;
    if (!isMainThread()) {
        WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&terminateWorkerContextTask, this));
        return;
    }
    m_webWorker->terminateWorkerContext();
}

void WebWorkerClientImpl::postMessageToWorkerContext(
    PassRefPtr<SerializedScriptValue> message,
    PassOwnPtr<MessagePortChannelArray> channels)
{
    // Worker.terminate() could be called from JS before the context is started.
    if (m_askedToTerminate)
        return;
    ++m_unconfirmedMessageCount;
    if (!isMainThread()) {
        WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&postMessageToWorkerContextTask,
                                                                   this,
                                                                   message->toWireString(),
                                                                   channels));
        return;
    }
    WebMessagePortChannelArray webChannels(channels.get() ? channels->size() : 0);
    for (size_t i = 0; i < webChannels.size(); ++i) {
        WebMessagePortChannel* webchannel =
                        (*channels)[i]->channel()->webChannelRelease();
        webchannel->setClient(0);
        webChannels[i] = webchannel;
    }
    m_webWorker->postMessageToWorkerContext(message->toWireString(), webChannels);
}

bool WebWorkerClientImpl::hasPendingActivity() const
{
    return !m_askedToTerminate
           && (m_unconfirmedMessageCount || m_workerContextHadPendingActivity);
}

void WebWorkerClientImpl::workerObjectDestroyed()
{
    if (isMainThread()) {
        m_webWorker->workerObjectDestroyed();
        m_worker = 0;
    }
    // Even if this is called on the main thread, there could be a queued task for
    // this object, so don't delete it right away.
    WebWorkerBase::dispatchTaskToMainThread(createCallbackTask(&workerObjectDestroyedTask,
                                                               this));
}

void WebWorkerClientImpl::postMessageToWorkerObject(const WebString& message,
                                                    const WebMessagePortChannelArray& channels)
{
    OwnPtr<MessagePortChannelArray> channels2;
    if (channels.size()) {
        channels2 = new MessagePortChannelArray(channels.size());
        for (size_t i = 0; i < channels.size(); ++i) {
            RefPtr<PlatformMessagePortChannel> platform_channel =
                            PlatformMessagePortChannel::create(channels[i]);
            channels[i]->setClient(platform_channel.get());
            (*channels2)[i] = MessagePortChannel::create(platform_channel);
        }
    }

    if (currentThread() != m_workerThreadId) {
        m_scriptExecutionContext->postTask(createCallbackTask(&postMessageToWorkerObjectTask,
                                                              this,
                                                              String(message),
                                                              channels2.release()));
        return;
    }

    postMessageToWorkerObjectTask(m_scriptExecutionContext.get(), this,
                                  message, channels2.release());
}

void WebWorkerClientImpl::postExceptionToWorkerObject(const WebString& errorMessage,
                                                      int lineNumber,
                                                      const WebString& sourceURL)
{
    if (currentThread() != m_workerThreadId) {
        m_scriptExecutionContext->postTask(createCallbackTask(&postExceptionToWorkerObjectTask,
                                                              this,
                                                              String(errorMessage),
                                                              lineNumber,
                                                              String(sourceURL)));
        return;
    }

    bool unhandled = m_worker->dispatchEvent(ErrorEvent::create(errorMessage,
                                                                sourceURL,
                                                                lineNumber));
    if (unhandled)
        m_scriptExecutionContext->reportException(errorMessage, lineNumber, sourceURL, 0);
}

void WebWorkerClientImpl::postConsoleMessageToWorkerObject(int destination,
                                                           int sourceId,
                                                           int messageType,
                                                           int messageLevel,
                                                           const WebString& message,
                                                           int lineNumber,
                                                           const WebString& sourceURL)
{
    if (currentThread() != m_workerThreadId) {
        m_scriptExecutionContext->postTask(createCallbackTask(&postConsoleMessageToWorkerObjectTask,
                                                              this,
                                                              sourceId,
                                                              messageType,
                                                              messageLevel,
                                                              String(message),
                                                              lineNumber,
                                                              String(sourceURL)));
        return;
    }

    m_scriptExecutionContext->addMessage(static_cast<MessageSource>(sourceId),
                                         static_cast<MessageType>(messageType),
                                         static_cast<MessageLevel>(messageLevel),
                                         String(message), lineNumber,
                                         String(sourceURL), 0);
}

void WebWorkerClientImpl::postConsoleMessageToWorkerObject(int sourceId,
                                                           int messageType,
                                                           int messageLevel,
                                                           const WebString& message,
                                                           int lineNumber,
                                                           const WebString& sourceURL)
{
    postConsoleMessageToWorkerObject(0, sourceId, messageType, messageLevel, message, lineNumber, sourceURL);
}

void WebWorkerClientImpl::confirmMessageFromWorkerObject(bool hasPendingActivity)
{
    // unconfirmed_message_count_ can only be updated on the thread where it's
    // accessed.  Otherwise there are race conditions with v8's garbage
    // collection.
    m_scriptExecutionContext->postTask(createCallbackTask(&confirmMessageFromWorkerObjectTask,
                                                          this));
}

void WebWorkerClientImpl::reportPendingActivity(bool hasPendingActivity)
{
    // See above comment in confirmMessageFromWorkerObject.
    m_scriptExecutionContext->postTask(createCallbackTask(&reportPendingActivityTask,
                                                          this,
                                                          hasPendingActivity));
}

void WebWorkerClientImpl::workerContextDestroyed()
{
}

void WebWorkerClientImpl::workerContextClosed()
{
}

void WebWorkerClientImpl::startWorkerContextTask(ScriptExecutionContext* context,
                                                 WebWorkerClientImpl* thisPtr,
                                                 const String& scriptURL,
                                                 const String& userAgent,
                                                 const String& sourceCode)
{
    thisPtr->m_webWorker->startWorkerContext(KURL(ParsedURLString, scriptURL),
                                             userAgent, sourceCode);
}

void WebWorkerClientImpl::terminateWorkerContextTask(ScriptExecutionContext* context,
                                                     WebWorkerClientImpl* thisPtr)
{
    thisPtr->m_webWorker->terminateWorkerContext();
}

void WebWorkerClientImpl::postMessageToWorkerContextTask(ScriptExecutionContext* context,
                                                         WebWorkerClientImpl* thisPtr,
                                                         const String& message,
                                                         PassOwnPtr<MessagePortChannelArray> channels)
{
    WebMessagePortChannelArray webChannels(channels.get() ? channels->size() : 0);

    for (size_t i = 0; i < webChannels.size(); ++i) {
        webChannels[i] = (*channels)[i]->channel()->webChannelRelease();
        webChannels[i]->setClient(0);
    }

    thisPtr->m_webWorker->postMessageToWorkerContext(message, webChannels);
}

void WebWorkerClientImpl::workerObjectDestroyedTask(ScriptExecutionContext* context,
                                                    WebWorkerClientImpl* thisPtr)
{
    if (thisPtr->m_worker) // Check we haven't alread called this.
        thisPtr->m_webWorker->workerObjectDestroyed();
    delete thisPtr;
}

void WebWorkerClientImpl::postMessageToWorkerObjectTask(
                                                        ScriptExecutionContext* context,
                                                        WebWorkerClientImpl* thisPtr,
                                                        const String& message,
                                                        PassOwnPtr<MessagePortChannelArray> channels)
{

    if (thisPtr->m_worker) {
        OwnPtr<MessagePortArray> ports =
            MessagePort::entanglePorts(*context, channels);
        RefPtr<SerializedScriptValue> serializedMessage =
            SerializedScriptValue::createFromWire(message);
        thisPtr->m_worker->dispatchEvent(MessageEvent::create(ports.release(),
                                                              serializedMessage.release()));
    }
}

void WebWorkerClientImpl::postExceptionToWorkerObjectTask(
                                                          ScriptExecutionContext* context,
                                                          WebWorkerClientImpl* thisPtr,
                                                          const String& errorMessage,
                                                          int lineNumber,
                                                          const String& sourceURL)
{
    bool handled = false;
    if (thisPtr->m_worker)
        handled = thisPtr->m_worker->dispatchEvent(ErrorEvent::create(errorMessage,
                                                                      sourceURL,
                                                                      lineNumber));
    if (!handled)
        thisPtr->m_scriptExecutionContext->reportException(errorMessage, lineNumber, sourceURL, 0);
}

void WebWorkerClientImpl::postConsoleMessageToWorkerObjectTask(ScriptExecutionContext* context,
                                                               WebWorkerClientImpl* thisPtr,
                                                               int sourceId,
                                                               int messageType,
                                                               int messageLevel,
                                                               const String& message,
                                                               int lineNumber,
                                                               const String& sourceURL)
{
    thisPtr->m_scriptExecutionContext->addMessage(static_cast<MessageSource>(sourceId),
                                                  static_cast<MessageType>(messageType),
                                                  static_cast<MessageLevel>(messageLevel),
                                                  message, lineNumber, sourceURL, 0);
}

void WebWorkerClientImpl::confirmMessageFromWorkerObjectTask(ScriptExecutionContext* context,
                                                             WebWorkerClientImpl* thisPtr)
{
    thisPtr->m_unconfirmedMessageCount--;
}

void WebWorkerClientImpl::reportPendingActivityTask(ScriptExecutionContext* context,
                                                    WebWorkerClientImpl* thisPtr,
                                                    bool hasPendingActivity)
{
    thisPtr->m_workerContextHadPendingActivity = hasPendingActivity;
}

} // namespace WebKit

#endif


text:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace OpenTkControl
{
    /// <summary>
    /// A WPF control that performs all OpenGL rendering on a thread separate from the UI thread to improve performance
    /// </summary>
    public class ThreadOpenTkControl : OpenTkControlBase
    {
        public static readonly DependencyProperty ThreadNameProperty = DependencyProperty.Register(
            nameof(ThreadName), typeof(string), typeof(ThreadOpenTkControl), new PropertyMetadata("OpenTk Render Thread"));

        /// <summary>
        /// The name of the background thread that does the OpenGL rendering
        /// </summary>
        public string ThreadName
        {
            get => (string) GetValue(ThreadNameProperty);
            set => SetValue(ThreadNameProperty, value);
        }

        /// <summary>
        /// This event is set to notify the thread to wake up when the control becomes visible
        /// </summary>
        private readonly ManualResetEvent _becameVisibleEvent = new ManualResetEvent(false);

        /// <summary>
        /// The Thread object for the rendering thread
        /// </summary>
        private Thread _renderThread;

        /// <summary>
        /// The CTS used to stop the thread when this control is unloaded
        /// </summary>
        private CancellationTokenSource _endThreadCts;

        public ThreadOpenTkControl()
        {
            IsVisibleChanged += OnIsVisibleChanged;
        }

        public override Task RunOnUiThread(Action action)
        {
            return Dispatcher.InvokeAsync(action).Task;
        }

        protected override void OnLoaded(object sender, RoutedEventArgs args)
        {
            base.OnLoaded(sender, args);

            _endThreadCts = new CancellationTokenSource();

            _renderThread = new Thread(RenderThread)
            {
                IsBackground = true,
                Priority = ThreadPriority.Highest,
                Name = ThreadName
            };
            _renderThread.Start(_endThreadCts.Token);
        }

        protected override void OnUnloaded(object sender, RoutedEventArgs args)
        {
            base.OnUnloaded(sender, args);

            _endThreadCts.Cancel();
            _renderThread.Join();
        }

        /// <summary>
        /// Wakes up the thread when the control becomes visible
        /// </summary>
        /// <param name="sender">The object that sent the event</param>
        /// <param name="args">The event arguments about this event</param>
        private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            bool visible = (bool)args.NewValue;

            if(visible)
                _becameVisibleEvent.Set();
        }

        /// <summary>
        /// The function that the thread runs to render the control
        /// </summary>
        /// <param name="boxedToken"></param>
        private void RenderThread(object boxedToken)
        {
#if DEBUG
            // Don't render in design mode to prevent errors from calling OpenGL API methods.
            if (Dispatcher.Invoke(() => IsDesignMode()))
                return;
#endif

            CancellationToken token = (CancellationToken) boxedToken;

            InitOpenGl();

            WaitHandle[] notContinousHandles = {token.WaitHandle, ManualRepaintEvent};
            WaitHandle[] notVisibleHandles   = {token.WaitHandle, _becameVisibleEvent};
            while (!token.IsCancellationRequested)
            {
                if (!_continuous)
                {
                    WaitHandle.WaitAny(notContinousHandles);
                }
                else if (!IsVisible)
                {
                    WaitHandle.WaitAny(notVisibleHandles);
                    _becameVisibleEvent.Reset();

                    if(!_continuous)
                        continue;
                }

                if (token.IsCancellationRequested)
                    break;

                ManualRepaintEvent.Reset();

                TimeSpan sleepTime = Render();
                if(sleepTime.CompareTo(TimeSpan.Zero) > 0)
                    Thread.Sleep(sleepTime);
            }

            DeInitOpenGl();
        }
    }
}


text:
package xjtu.se.hmbb.dataStruct;

import java.io.*;
import java.util.*;

/**
 * Created by haoyang on 2017/5/6.
 */
public class AMGraph {
    private List<String> vertexList;                 //点的集合
    private int [][] edges;                         //存储边的矩阵
    private int numOfEdges;                         //边的个数
    private int start;                              //开始节点的下标
    private int end;                                //结束节点的下标
    private List<Integer> fruitRoomList;            //水果间,必经过的节点下标
    private List<int[]> anteaterPath;           //食蚁兽所在的边
    private List<int[]> rewardPath;              //带有奖励的边

    public AMGraph(File file) {
        this.numOfEdges = 0;
        this.vertexList = new ArrayList<>();
        this.fruitRoomList = new ArrayList<>();
        this.anteaterPath = new ArrayList<>();
        this.rewardPath = new ArrayList<>();

        int sentry = 0;

        Map<String, Integer> nodeToIndex = new HashMap<>();

        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));

            String line = "";
            while((line = reader.readLine()) != null) {
                if(line.trim().equals("")) {
                    sentry++;
                    continue;
                }

                String[] charList = line.trim().split(" ");
                // 如果哨兵值为0,获取节点个数,并初始化权重的二维数组
                if(sentry == 0) {
                    int numOfIndex = Integer.parseInt(charList[0]);
                    this.edges = new int[numOfIndex][numOfIndex];
                    for(int i = 0; i < numOfIndex; i++) {
                        for(int j = 0; j < numOfIndex; j++) {
                            edges[i][j] = Integer.MAX_VALUE;
                        }
                    }
                } else if(sentry == 1) {  // 如果哨兵值为0,读取边和节点
                    int startIndex = 0;
                    int endIndex = 0;

                    if(nodeToIndex.containsKey(charList[0])) {
                        startIndex = nodeToIndex.get(charList[0]);
                    } else {
                        startIndex = this.vertexList.size();

                        //获取初始节点和结束节点的下标
                        if (charList[0].equals("S")) {
                            this.start = startIndex;
                        } else if (charList[0].equals("E")) {
                            this.end = startIndex;
                        }

                        nodeToIndex.put(charList[0], startIndex);
                        this.vertexList.add(charList[0]);
                    }

                    if(nodeToIndex.containsKey(charList[1])) {
                        endIndex = nodeToIndex.get(charList[1]);
                    } else {
                        endIndex = this.vertexList.size();

                        if (charList[1].equals("S")) {
                            this.start = endIndex;
                        } else if (charList[1].equals("E")) {
                            this.end = endIndex;
                        }

                        nodeToIndex.put(charList[1], endIndex);
                        this.vertexList.add(charList[1]);
                    }

                    this.numOfEdges++;

                    //将边的权重加入edge中
                    int weight = Integer.parseInt(charList[2]);
                    this.edges[startIndex][endIndex] = weight;
                    this.edges[endIndex][startIndex] = weight;
                } else if(sentry == 2) { // 如果哨兵值为1,读取食蚁兽路径
                    int[] anteaterPathList = new int[2];
                    anteaterPathList[0] = nodeToIndex.get(charList[0]);
                    anteaterPathList[1] = nodeToIndex.get(charList[1]);
                    this.anteaterPath.add(anteaterPathList);
                } else if(sentry == 3) { //如果哨兵值为2,读取奖励的必过路径
                    int[] rewardPathList = new int[2];
                    rewardPathList[0] = nodeToIndex.get(charList[0]);
                    rewardPathList[1] = nodeToIndex.get(charList[1]);
                    this.rewardPath.add(rewardPathList);
                } else if(sentry == 4) { //如果哨兵值为3, 读取水果间
                    for(String node: charList) {
                        this.fruitRoomList.add(nodeToIndex.get(node));
                    }
                }
            }
            reader.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }

    }

    public List<String> getVertexList() {
        return vertexList;
    }

    public void setVertexList(List<String> vertexList) {
        this.vertexList = vertexList;
    }

    public int[][] getEdges() {
        return edges;
    }

    public void setEdges(int[][] edges) {
        this.edges = edges;
    }

    public int getNumOfEdges() {
        return numOfEdges;
    }

    public void setNumOfEdges(int numOfEdges) {
        this.numOfEdges = numOfEdges;
    }

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getEnd() {
        return end;
    }

    public void setEnd(int end) {
        this.end = end;
    }

    public List<Integer> getFruitRoomList() {
        return fruitRoomList;
    }

    public void setFruitRoomList(List<Integer> fruitRoomList) {
        this.fruitRoomList = fruitRoomList;
    }

    public List<int[]> getAnteaterPath() {
        return anteaterPath;
    }

    public void setAnteaterPath(List<int[]> anteaterPath) {
        this.anteaterPath = anteaterPath;
    }

    public List<int[]> getRewardPath() {
        return rewardPath;
    }

    public void setRewardPath(List<int[]> rewardPath) {
        this.rewardPath = rewardPath;
    }
}


text:
import {setFlagsFromString} from 'v8';
import {runInNewContext} from 'vm';
import prettyFormat = require('pretty-format');
import {isPrimitive} from 'jest-get-type';

export default class {
  private _isReferenceBeingHeld: boolean;

  constructor(value: unknown) {
    if (isPrimitive(value)) {
      throw new TypeError(
        [
          'Primitives cannot leak memory.',
          'You passed a ' + typeof value + ': <' + prettyFormat(value) + '>',
        ].join(' '),
      );
    }

    let weak: typeof import('weak-napi');

    try {
      // eslint-disable-next-line import/no-extraneous-dependencies
      weak = require('weak-napi');
    } catch (err) {
      if (!err || err.code !== 'MODULE_NOT_FOUND') {
        throw err;
      }

      throw new Error(
        'The leaking detection mechanism requires the "weak-napi" package to be installed and work. ' +
          'Please install it as a dependency on your main project',
      );
    }

    weak(value as object, () => (this._isReferenceBeingHeld = false));
    this._isReferenceBeingHeld = true;

    // Ensure value is not leaked by the closure created by the "weak" callback.
    value = null;
  }

  isLeaking(): Promise<boolean> {
    this._runGarbageCollector();

    return new Promise(resolve =>
      setImmediate(() => resolve(this._isReferenceBeingHeld)),
    );
  }

  private _runGarbageCollector() {
    const isGarbageCollectorHidden = !global.gc;

    // GC is usually hidden, so we have to expose it before running.
    setFlagsFromString('--expose-gc');
    runInNewContext('gc')();

    // The GC was not initially exposed, so let's hide it again.
    if (isGarbageCollectorHidden) {
      setFlagsFromString('--no-expose-gc');
    }
  }
}


text:
local Enumerable = require('enumerable')

describe("Enumerable", function()
  describe("create()", function()

    describe("when instantiated with no data", function()
      local instance = Enumerable.create()

      it("stores an empty table", function()
        assert.are.same({}, instance._data)
      end)

      describe("when created with an existing table", function()
        local data = {'test'}
        local instance = Enumerable.create(data)
        it("uses existing table data", function()
          assert.are.equal(data, instance._data)
        end)
      end)

      describe("when created with invalid data", function()
        it("throws an error", function()
          assert.has_error(function() Enumerable.create('not a table') end, 'Enumerable data must be a sequence')
          assert.has_error(function() Enumerable.create(10) end, 'Enumerable data must be a sequence')
        end)
      end)

      describe("when created with a non-sequence table", function()
        it("throws an error", function()
          assert.has_error(function() Enumerable.create({field = 'value'}) end, 'Enumerable data must be a sequence')

          local data = {1,2,3}
          data[2] = nil

          assert.has_error(function() Enumerable.create(data) end, 'Enumerable data must be a sequence')
        end)
      end)
    end)
  end)

  describe("Instance methods", function()
    describe("data()", function()
      local data = {'test'}
      local instance = Enumerable.create(data)

      it("returns raw table data", function()
        assert.are.equal(data, instance:data())
      end)
    end)

    describe("to_table()", function()
      local data = {'test'}
      local complexData = {'test', data}

      it("clones internal data", function()
        local result = Enumerable.create(data):to_table()

        assert.are_not.equal(data, result)
        assert.same(result, data)
      end)

      it("copies child content by reference", function()
        local result = Enumerable.create(complexData):to_table()

        assert.are_not.equal(data, result)
        assert.are.equal(data, result[2])
      end)
    end)

    describe("empty()", function()
      describe("when collection contains no elements", function()
        local instance = Enumerable.create({})

        it("is considered empty", function()
          assert.is_true(instance:empty())
        end)
      end)

      describe("when collection contains elements", function()
        local instance = Enumerable.create({1,2,3})

        it("is considered empty", function()
          assert.is_false(instance:empty())
        end)
      end)
    end)

    describe("each()", function()
      local instance = Enumerable.create({'a', 'b', 'c'})

      it("applies callback to enumerable items", function()
        local callback = spy.new(function() end)
        instance:each(callback)

        assert.spy(callback).was.called_with('a', 1)
        assert.spy(callback).was.called_with('b', 2)
        assert.spy(callback).was.called_with('c', 3)
        assert.spy(callback).was.called(3)
      end)

      it("returns the enumerable instance", function()
        assert.are.equal(instance, instance:each(function() end))
      end)
    end)
  end)

  describe("map()", function()
    local instance = Enumerable.create({10,20,30})

    it("returns a new Enumerable instance", function()
      local result = instance:map(function() end)

      assert.are.equal('table', type(result))
      assert.are_not.equal(instance, result)
    end)

    it("calls provided function for each table element", function()
      local callback = spy.new(function() end)
      instance:map(callback)

      assert.spy(callback).was.called_with(10,1)
      assert.spy(callback).was.called_with(20, 2)
      assert.spy(callback).was.called_with(30,3)
      assert.spy(callback).was.called(3)
    end)

    it("applies callback to table elements", function()
      local result = instance:map(function(v) return v * 2 end)

      assert.are.same({20, 40, 60}, result:data())
    end)

    it("compacts arrays when callback returns nil", function()
      local result = instance:map(function(v, i) return i > 1 and v or nil end)

      assert.are.same({20, 30}, result:data())
    end)

    it("returns a new enumerable instance", function()
      local result = instance:map(function(i) return i end)

      assert.are_not.equal(instance, result)
      assert.are.same(instance, result)
    end)
  end)

  describe("find_index()", function()
    local instance = Enumerable.create({5, 10, 15})
    local callback = function(v, i) return v > 6 end

    it("returns the position of the first matching result", function()
      assert.are.equal(2, instance:find_index(callback))
    end)
  end)

  describe("first()", function()
    local instance = Enumerable.create({5, 10, 15, 20})

    describe("with no arguments", function()
      it("returns the first table element", function()
        assert.are.equal(5, instance:first())
      end)
    end)

    describe("with a count lower than available table elements", function()
      it("returns the requested number of elements", function()
        assert.are.same({5, 10, 15}, instance:first(3))
      end)
    end)

    describe("with a count greater than available table elements", function()
      it("returns the maximum number of elements", function()
        assert.are.same({5, 10, 15, 20}, instance:first(6))
      end)
    end)
  end)

  describe("last()", function()
    local instance = Enumerable.create({5, 10, 15, 20})

    describe("with no arguments", function()
      it("returns the last table element", function()
        assert.are.equal(20, instance:last())
      end)
    end)

    describe("with a count lower than available table elements", function()
      it("returns the requested number of elements from the end of the table", function()
        assert.are.same({10, 15, 20}, instance:last(3))
      end)
    end)

    describe("with a count greater than available table elements", function()
      it("returns the maximum number of elements", function()
        assert.are.same({5, 10, 15, 20}, instance:last(6))
      end)
    end)
  end)

  describe("count()", function()
    local instance = Enumerable.create({1,2,3,4})

    describe("when called without a callback", function()
      it("returns the internal table length", function()
        assert.are.equal(4, instance:count())
      end)
    end)

    describe("when called with a callback", function()
      local callback = function(item) return item > 2 end

      it("returns the count of elements based on callback", function()
        assert.are.equal(2, instance:count(callback))
      end)
    end)
  end)

  describe("concat()", function()
    local append = {4,5,6}

    it("appends new content to the end of an existing table", function()
      local instance = Enumerable.create({1,2,3})
      assert.are.same({1,2,3,4,5,6}, instance:concat(append):data())
    end)

    it("returns the enumerable instance", function()
      local instance = Enumerable.create({1,2,3})
      assert.are.same(instance, instance:concat(append))
    end)
  end)

  describe("reduce()", function()
    local instance = Enumerable.create({1,2,3})

    it("applies callback to each element", function()
      local callback = spy.new(function() end)

      instance:reduce(callback)

      assert.spy(callback).was.called_with(nil, 1, 1)
      assert.spy(callback).was.called_with(nil, 2, 2)
      assert.spy(callback).was.called_with(nil, 3, 3)
      assert.spy(callback).was.called(3)
    end)

    describe("with an invalid callback", function()
      it("throws an error", function()
        assert.has_error(function() instance:reduce({}) end, 'Callback must be a function or table')
        assert.has_error(function() instance:reduce() end, 'Callback must be a function or table')
      end)
    end)

    describe("without an initial value", function()
      local callback = function(reduce, value) return (reduce or 0) + value end

      it("returns the result of the callback applied to list items", function()
        assert.are.equal(6, instance:reduce(callback))
      end)
    end)

    describe("with an initial value", function()
      local callback = function(reduce, value) return reduce + value end

      it("begins reduction with a seeded value", function()
        assert.are.equal(16, instance:reduce(10, callback))
      end)
    end)
  end)

  describe("min()", function()
    local instance = Enumerable.create({3,5,1,4,2})

    describe("when called without a callback", function()
      it("returns the lowest value in a sequence", function()
        assert.are.equal(1, instance:min())
      end)
    end)

    describe("when called with a callback", function()
      it("applies callback to each element", function()
        local callback = spy.new(function() end)

        instance:min(callback)

        assert.spy(callback).was.called_with(3)
        assert.spy(callback).was.called_with(5)
        assert.spy(callback).was.called_with(1)
        assert.spy(callback).was.called_with(4)
        assert.spy(callback).was.called_with(2)
        assert.spy(callback).was.called(5)
      end)

      it("returns the value of the item with the lowest callback result", function()
        local callback = function(v) return v == 4 and 1 or 2 end

        assert.are.equal(4, instance:min(callback))
      end)
    end)
  end)

  describe("max()", function()
    local instance = Enumerable.create({3,5,1,4,2})

    describe("when called without a callback", function()
      it("returns the highest value in a sequence", function()
        assert.are.equal(5, instance:max())
      end)
    end)

    describe("when called with a callback", function()
      it("applies callback to each element", function()
        local callback = spy.new(function() end)

        instance:max(callback)

        assert.spy(callback).was.called_with(3)
        assert.spy(callback).was.called_with(5)
        assert.spy(callback).was.called_with(1)
        assert.spy(callback).was.called_with(4)
        assert.spy(callback).was.called_with(2)
        assert.spy(callback).was.called(5)
      end)

      it("returns the value of the item with the highest callback result", function()
        local callback = function(v) return v == 4 and 2 or 1 end

        assert.are.equal(4, instance:max(callback))
      end)
    end)
  end)

  describe("minmax()", function()
    describe("when called without a callback", function()
      local instance = Enumerable.create({3,5,1,4,2})

      it("returns the highest and lowest values in a sequence", function()
        local min, max = instance:minmax()
        assert.are.equal(1, min)
        assert.are.equal(5, max)
      end)
    end)

    describe("when called with a callback", function()
      local data = {'bbb','aaaa','c','dd'}
      local instance = Enumerable.create(data)

      it("applies callback to each element", function()
        local callback = spy.new(function() end)

        instance:minmax(callback)

        assert.spy(callback).was.called(8)
      end)

      it("uses callback for min and max comparison", function()
        local min, max = instance:minmax(function(v) return #v end)

        assert.are.equal('c', min)
        assert.are.equal('aaaa', max)
      end)
    end)
  end)

  describe("sort()", function()
    it("returns the enumerable instance", function()
      local instance =  Enumerable.create({5,1,4,3,2})

      assert.are.equal(instance, instance:sort())
    end)

    describe("when called without a callback", function()
      local instance =  Enumerable.create({5,1,4,3,2})

      it("sorts elements in ascending order", function()
        assert.are.same({1,2,3,4,5}, instance:sort():data())
      end)
    end)

    describe("when called with a callback", function()
      local instance =  Enumerable.create({5,1,4,3,2})
      local callback = function(a, b) return b < a end

      it("sorts elements based on callback result", function()
        assert.are.same({5,4,3,2,1}, instance:sort(callback):data())
      end)
    end)
  end)

  describe("push()", function()
    it("returns the enumerable instance", function()
      local instance = Enumerable.create()

      assert.are.equal(instance, instance:push(1))
    end)

    it("adds new items to the end of the list", function()
      local instance = Enumerable.create({1, 2})

      assert.are.same({1,2,3,4}, instance:push(3, 4):data())
    end)
  end)

  describe("pop()", function()
    it("returns the last item in the sequence", function()
      local instance = Enumerable.create({1,2,3})
      assert.are.equal(3, instance:pop())
    end)

    it("removes the last item ine the sequence", function()
      local instance = Enumerable.create({1,2,3})
      instance:pop()

      assert.are.same({1,2}, instance:data())
    end)
  end)

  describe("shift()", function()
    it("returns the first item in the sequence", function()
      local instance = Enumerable.create({1,2,3})
      assert.are.equal(1, instance:shift())
    end)

    it("removes the first item ine the sequence", function()
      local instance = Enumerable.create({1,2,3})
      instance:shift()

      assert.are.same({2,3}, instance:data())
    end)
  end)

  describe("unshift()", function()
    it("returns the enumerable instance", function()
      local instance = Enumerable.create()

      assert.are.equal(instance, instance:unshift(1))
    end)

    it("adds new items to the beginning of the list", function()
      local instance = Enumerable.create({1,2})

      assert.are.same({10, 11, 1, 2}, instance:unshift(10, 11):data())
    end)
  end)

  describe("find()", function()
    local instance = Enumerable.create({10, 20, 30})
    local callback = function(v) return v > 15 end

    it("finds the first element matching a callback", function()
      assert.are.equal(20, instance:find(callback))
    end)
  end)

  describe("reject()", function()
    local instance = Enumerable.create({1,2,3,4,5,6})

    it("applies callback to each element", function()
      local callback = spy.new(function() end)

      instance:reject(callback)

      assert.spy(callback).was.called_with(1, 1)
      assert.spy(callback).was.called_with(2, 2)
      assert.spy(callback).was.called_with(3, 3)
      assert.spy(callback).was.called_with(4, 4)
      assert.spy(callback).was.called_with(5, 5)
      assert.spy(callback).was.called_with(6, 6)
      assert.spy(callback).was.called(6)
    end)

    it("returns an instance with items removed based on callback result", function()
      local result = instance:reject(function(v) return v % 2 == 0 end)

      assert.are.same({1,3,5}, result:data())
    end)

    it("returns a new enumerable instance", function()
      local result = instance:reject(function() end)

      assert.are_not.equal(instance, result)
      assert.are.same(instance, result)
    end)
  end)

  describe("select()", function()
    local instance = Enumerable.create({1,2,3,4,5,6})
     it("applies callback to each element", function()
      local callback = spy.new(function() end)

      instance:reject(callback)

      assert.spy(callback).was.called_with(1, 1)
      assert.spy(callback).was.called_with(2, 2)
      assert.spy(callback).was.called_with(3, 3)
      assert.spy(callback).was.called_with(4, 4)
      assert.spy(callback).was.called_with(5, 5)
      assert.spy(callback).was.called_with(6, 6)
      assert.spy(callback).was.called(6)
    end)

    it("returns an instance with items included based on callback result", function()
      local result = instance:select(function(v) return v % 2 == 0 end)

      assert.are.same({2,4,6}, result:data())
    end)

    it("returns a new enumerable instance", function()
      local result = instance:select(function() return true end)

      assert.are_not.equal(instance, result)
      assert.are.same(instance, result)
    end)
  end)

  describe("all()", function()
    local instance = Enumerable.create({10, 20, 30, 40})

    describe("when all elements match callback criteria", function()
      local callback = function(v) return v > 5 end

      it("returns true", function()
        assert.is_true(instance:all(callback))
      end)
    end)

    describe("when any elements do not match callback criteria", function()
      local callback = function(v) return v < 39 end

      it("returns false", function()
        assert.is_false(instance:all(callback))
      end)
    end)
  end)

  describe("any()", function()
    local instance = Enumerable.create({10, 20, 30, 40})

    describe("when any elements match callback criteria", function()
      local callback = function(v) return v > 35 end

      it("returns true", function()
        assert.is_true(instance:any(callback))
      end)
    end)

    describe("when no elements match callback criteria", function()
      local callback = function(v) return v > 50 end

      it("returns false", function()
        assert.is_false(instance:any(callback))
      end)
    end)
  end)

  describe("group_by()", function()
    local instance = Enumerable.create({'apple', 'amber', 'candy', 'pumpkin'})
    local callback = function(v) return string.sub(v, 1, 1) end

    it("creates multiple lists based on callback criteria", function()
      local result = instance:group_by(callback)
      local expected = {
        a = Enumerable.create({'apple', 'amber'}),
        c = Enumerable.create({'candy'}),
        p = Enumerable.create({'pumpkin'}),
      }

      assert.are.same(expected, result)
    end)
  end)

  describe("partition()", function()
    local callback = function(v) return v % 2 == 0 end

    it("creates lists based on boolean callback result", function()
      local instance = Enumerable.create({1,2,3,4})
      local evenResult, oddResult = instance:partition(callback)

      assert.are.same({2,4}, evenResult:data())
      assert.are.same({1,3}, oddResult:data())
    end)

    describe("when there are no results", function()
      it("return partitioned tables", function()
        local instance = Enumerable.create()
        local truthyResult, falseyResult = instance:partition(callback)

        assert.are.same({}, truthyResult:data())
        assert.are.same({}, falseyResult:data())
      end)
    end)
  end)

  describe("delegation", function()
    local instance = Enumerable.create({6,5,4,3,2,1})

    it("it delegates index methods to internal table", function()
      assert.are.equal(5, instance[2])
    end)

    it("returns nil for keys missing from internal table", function()
      assert.is_equal(nil, instance[7])
    end)
  end)
end)


text:
{-
Copyright 2012-2013 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}

{-# Language FlexibleInstances, TypeSynonymInstances, TypeFamilies  #-}

module Plush.Run.TestExec (
    TestState(), initialTestState,
    TestExec, runTest, testOutput,
    )
    where

import Control.Applicative ((<$>), (<*>))
import Control.Exception (SomeException)
import Control.Monad (unless, when)
import Control.Monad.Exception (ExceptionT, runExceptionT, throwM)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.State
import qualified Data.ByteString.Lazy as L
--import qualified Data.ByteString.Lazy.UTF8 as L
import qualified Data.HashMap.Strict as M
import qualified Data.IntMap as I
import Data.List (foldl')
import Data.Maybe (isJust, isNothing, fromMaybe)
import qualified Data.Text.Encoding.Error as T
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Encoding as LT
import System.FilePath
import System.IO.Error

import Plush.Run.BuiltIns
import Plush.Run.BuiltIns.Utilities
import Plush.Run.Posix
import Plush.Run.Posix.Return
import Plush.Run.Posix.Utilities
import Plush.Run.Types

-- File System

type DirPath = FilePath
type Name = String
data Entry = FileItem Int | DirItem

data IType = IDevNull | IFile | IExec | IPipe
data INode = INode IType L.ByteString

data FileSystem = FileSystem
    { fsTree :: M.HashMap DirPath (M.HashMap Name Entry)
    , fsStore :: I.IntMap INode
    }

fsDirectoryContents :: FileSystem -> DirPath -> Maybe [Name]
fsDirectoryContents (FileSystem tree _) dp =
    M.lookup dp tree >>= return . (".":) . ("..":) . M.keys

fsDirectoryExists :: FileSystem -> DirPath -> Bool
fsDirectoryExists (FileSystem tree _) dp = isJust $ M.lookup dp tree

fsFileExists :: FileSystem -> DirPath -> Name -> Bool
fsFileExists fs dp n = maybe False isFile $ fsItemEntry fs dp n
  where
    isFile (FileItem _) = True
    isFile _ = False

fsExecutable :: FileSystem -> DirPath -> Name -> Maybe (RegularUtility TestExec)
fsExecutable fs dp n = fsItemEntry fs dp n >>= iNode >>= getExec
  where
    iNode (FileItem i) = I.lookup i (fsStore fs)
    iNode _ = Nothing
    getExec (INode IExec _) = M.lookup n testExecs
    getExec _ = Nothing
    -- TODO(mzero): should return Either String with erorr messages

fsItemEntry :: FileSystem -> DirPath -> Name -> Maybe Entry
fsItemEntry _ "/" "." = Just DirItem
fsItemEntry (FileSystem tree _) dp n = M.lookup dp tree >>= M.lookup n

-- NB: the add and remove functions will simply do nothing if the operation
-- would produce an illegal state. It is the job of the higher level code
-- to test preconditions, and signal failures.

fsAddDirectory :: FileSystem -> DirPath -> Name -> FileSystem
fsAddDirectory fs@(FileSystem tree _) dp n =
    if isJust (fsItemEntry fs dp n)
        then fs
        else fs { fsTree = addDir . addEntry $ tree }
  where
    addEntry = M.adjust (M.insert n DirItem) dp
    addDir = M.insert (dp </> n) M.empty

fsAddINode :: IType -> FileSystem -> DirPath -> Name -> FileSystem
fsAddINode itype fs@(FileSystem tree store) dp n =
    if isJust (fsItemEntry fs dp n)
        then fs
        else FileSystem tree' store'
  where
    i = if I.null store then 0 else (+ 1) . fst . I.findMax $ store
    tree' = M.adjust (M.insert n (FileItem i)) dp tree
    store' = I.insert i (INode itype L.empty) store

fsAddFile :: FileSystem -> DirPath -> Name -> FileSystem
fsAddFile = fsAddINode IFile

fsRemove :: FileSystem -> DirPath -> Name -> FileSystem
fsRemove fs@(FileSystem tree _) dp n =
    case fsItemEntry fs dp n of
        Nothing -> fs
        Just (FileItem _) -> fs { fsTree = removeEntry tree }
        Just DirItem -> if maybe False M.null (M.lookup dpn tree)
            then fs { fsTree = removeDir . removeEntry $ tree }
            else fs
  where
    dpn = dp </> n
    removeEntry = M.adjust (M.delete n) dp
    removeDir = M.delete dpn

fsTruncFile :: FileSystem -> DirPath -> Name -> FileSystem
fsTruncFile fs@(FileSystem _tree store) dp n =
    case fsItemEntry fs dp n of
        Just (FileItem i) -> case I.lookup i store of
            Just (INode itype _) ->
                fs { fsStore = I.insert i (INode itype L.empty) store }
            _ -> fs
        _ -> fs

initialFileSystem :: FileSystem
initialFileSystem = foldl' (flip ($)) rootFS $
    map addDir [ ("/", "bin")
               , ("/", "dev")
               , ("/", "home")
               , ("/", "tmp")
               , ("/", "proc")
               ]
    ++ map addDev [("null", IDevNull)]
    ++ map addPipe ["stdin", "stdout", "stderr"]
    ++ map addExec (M.keys testExecs)
  where
    rootFS = FileSystem rootTree I.empty
    rootTree = M.singleton "/" M.empty
    addDir (dp, n) fs = fsAddDirectory fs dp n
    addDev (n, itype) fs = fsAddINode itype fs "/dev" n
    addPipe n fs = fsAddINode IPipe fs "/proc" n
    addExec n fs = fsAddINode IExec fs "/bin" n

testExecs :: M.HashMap String (RegularUtility TestExec)
testExecs = pseudoExecs

data FDesc = FDesc {
    fdReadAll :: TestExec L.ByteString,
    fdWrite :: L.ByteString -> TestExec ()
    }

iNodeFDesc :: Int -> IType -> FDesc
iNodeFDesc i itype = FDesc iReadAll iWrite
  where
    iReadAll = do
        s <- lift get
        case I.lookup i $ fsStore $ tsFileSystem s of
            Nothing -> return L.empty
            Just (INode IDevNull _) -> return L.empty
            Just (INode IFile bs) -> return bs
            Just (INode IExec _) -> return L.empty
            Just (INode IPipe bs) -> iSetBuf s L.empty >> return bs
    iWrite as = do
        s <- lift get
        case I.lookup i $ fsStore $ tsFileSystem s of
            Nothing -> return ()
            Just (INode IDevNull _) -> return ()
            Just (INode IFile bs) -> iSetBuf s (L.append bs as)
            Just (INode IExec _) -> return ()
            Just (INode IPipe bs) -> iSetBuf s (L.append bs as)
    iSetBuf s nbs = do
        let nis = INode itype nbs
        let fs = tsFileSystem s
        let fs' = fs { fsStore = I.insert i nis $ fsStore fs }
        let s' = s { tsFileSystem = fs' }
        lift $ put s'

contentFDesc :: L.ByteString -> FDesc
contentFDesc content = FDesc (return content) (\_ -> return ())

data TestState = TestState
    { tsWorkingDir :: FilePath      -- ^ absolute path to current working dir
    , tsFileSystem :: FileSystem    -- ^ mock file system
    , tsFDescs :: I.IntMap FDesc    -- ^ file descriptors
    }

initialTestState :: TestState
initialTestState = snd $ runTest startup ts0
  where
    startup = do
        _ <- openFile "/proc" "stdin"
        _ <- openFile "/proc" "stdout"
        _ <- openFile "/proc" "stderr"
        return ()
        -- TODO: refactor to call a lower level function to ensure which FDs
        -- these end up on, rather than relying on the allocation order
    ts0 = TestState
        { tsWorkingDir = "/home"
        , tsFileSystem = initialFileSystem
        , tsFDescs = I.empty
        }

canonicalizePath :: TestState -> FilePath -> (FilePath, DirPath, Name)
canonicalizePath ts fp = parts $ reducePath $ tsWorkingDir ts </> fp
  where
    parts [] = ("", "", "") -- should never happen
    parts ["/"] = ("/", "/", ".")
    parts [n] = (n, ".", n) -- relative paths should never happen
    parts (n:ns) = let dp = joinPath (reverse ns) in (dp </> n, dp, n)

nextFreeAfter :: I.IntMap a -> I.Key -> Int
nextFreeAfter m i = if i `I.notMember` m then i else nextFreeAfter m (succ i)

-- Test Execution Monad

type TestExec = ExceptionT (State TestState)
runTest :: TestExec a -> TestState -> (Either SomeException a, TestState)
runTest = runState . runExceptionT

testOutput :: TestExec (String, String)
testOutput = do
    so <- utos `fmap` readAll stdOutput
    se <- utos `fmap` readAll stdError
    return (so, se)
  where
    utos = LT.unpack . LT.decodeUtf8With T.lenientDecode

instance PosixLike TestExec where
    createDirectory fp _mode = runFilePrim fp $ \_s fs fpc dpc n -> do
        directoryMustNotExist "createDirectory" fp fs fpc
        directoryMustExist "createDirectory" fp fs dpc
        updateFileSystem $ fsAddDirectory fs dpc n

    removeDirectory fp = runFilePrim fp $ \_s fs fpc dpc n -> do
        directoryMustExist "removeDirectory" fp fs fpc
        unless (maybe False ((==2).length) $ fsDirectoryContents fs fpc) $
            raise illegalOperationErrorType "removeDirectory" fp
        updateFileSystem $ fsRemove fs dpc n

    getDirectoryContents fp = runFilePrim fp $ \_s fs fpc _dpc _n -> do
        directoryMustExist "getDirectoryContents" fp fs fpc
        let contents = fsDirectoryContents fs fpc
        return $ fromMaybe [] contents

    getWorkingDirectory = lift get >>= return . tsWorkingDir
    changeWorkingDirectory fp = runFilePrim fp $ \s fs fpc _dpc _n -> do
        directoryMustExist "changeWorkingDirectory" fp fs fpc
        updateTestState $ s { tsWorkingDir = fpc }

    getInitialEnvironment = return
        [ ("HOME", "/home")
        , ("LOGNAME", "tester")
        , ("PATH", "/bin")
        , ("PWD", "/home")
        , ("SHELL", "/usr/bin/plush")
        , ("TMPDIR", "/tmp")
        ]

    type FileStatus TestExec = Entry

    getFileStatus fp = runFilePrim fp $ \_s fs _fpc dpc n -> do
        let stat = fsItemEntry fs dpc n
        maybe (raise doesNotExistErrorType "getFileStatus" fp) return stat
    getSymbolicLinkStatus = getFileStatus

    isExecutable fp = runFilePrim fp $ \_s fs _fpc dpc n -> return $
        isJust $ fsExecutable fs dpc n

    removeLink fp = runFilePrim fp $ \_s fs _fpc dpc n -> do
        fileMustExist "removeLink" fp fs dpc n
        updateFileSystem $ fsRemove fs dpc n

    setFileTimes _ _ _ = return ()
    touchFile fp = runFilePrim fp $ \_s fs _fpc dpc n -> do
        fileMustExist "touchFile" fp fs dpc n

    openFd fp _rw mMode opts = runFilePrim fp $ \_s fs _fpc dpc n -> do
        when (isNothing mMode) $ fileMustExist "openFd" fp fs dpc n
        if (fsFileExists fs dpc n)
            then when (trunc opts) $ updateFileSystem $ fsTruncFile fs dpc n
            else updateFileSystem $ fsAddFile fs dpc n
        openFile dpc n
    createFile fp _mode = runFilePrim fp $ \_s fs _fpc dpc n -> do
        fileMustNotExist "createFile" fp fs dpc n
        directoryMustExist "createFile" fp fs dpc
        updateFileSystem $ fsAddFile fs dpc n
        openFile dpc n
    closeFd fd = runFdPrim "closeFd" fd $ \s fds _desc -> do
        lift $ put s { tsFDescs = I.delete (fromIntegral fd) fds }

    readAll fd = runFdPrim "readAll" fd $ \_s _fds desc -> fdReadAll desc
    readLine fd = runFdPrim "readLine" fd $ readLinePrim fd
    write fd bs = runFdPrim "write" fd $ \_s _fds desc -> fdWrite desc bs
    dupTo fdFrom fdTo =
        runFdPrim "dupTo" fdFrom $ \s fds desc ->
            lift $ put s { tsFDescs = I.insert (fromIntegral fdTo) desc fds }
    dupFdCloseOnExec fdFrom fdMin =
        runFdPrim "dupFdCloseOnExec" fdFrom $ \s fds desc ->
            let dest = nextFreeAfter fds $ fromIntegral fdMin
            in lift $ do
                put s { tsFDescs = I.insert dest desc fds }
                return $ fromIntegral dest

    setCloseOnExec _ = return ()

    getUserHomeDirectoryForName s = return $ lookup s homeDirs
      where
        homeDirs = [("tester","/home"), ("root","/"), ("nobody","/tmp")]
    realAndEffectiveIDsMatch = return True

    getProcessID = return 42

    execProcess fp _env _cmd args = runFilePrim fp $ \_s fs _fpc dpc n -> do
        case fsExecutable fs dpc n of
            Just util -> utilExecute util args
                -- TODO(mzero): doesn't handle environment correctly, but
                -- currently none of the pseudoExecs care about it
            Nothing -> exitMsg 127
                        $ fp ++ ": No such file or directory, or not executable"

    captureStdout action = (,) <$> action <*> readAll stdOutput

    pipeline [] = return ExitSuccess
    pipeline (c0:cs) = c0 >>= next cs
      where
        next [] e = return e
        next (c:cs') _ = do
            readAll stdOutput >>= write stdInput
            c >>= next cs'

    contentFd = openFDesc . contentFDesc

instance PosixLikeFileStatus Entry where
    accessTime _ = fromInteger 0
    modificationTime _ = fromInteger 0

    isRegularFile (FileItem _) = True
    isRegularFile _ = False
    isDirectory DirItem = True
    isDirectory _ = False
    isSymbolicLink _ = False

type FilePrim a = TestState -> FileSystem
                -> FilePath -> DirPath -> Name -> a

runFilePrim :: FilePath -> FilePrim (TestExec a) -> TestExec a
runFilePrim fp prim = do
    s <- lift get
    let fs = tsFileSystem s
    let (fpc, dpc, n) = canonicalizePath s fp
    prim s fs fpc dpc n

type FdPrim a = TestState -> I.IntMap FDesc -> FDesc -> a

runFdPrim :: String -> Fd -> FdPrim (TestExec a) -> TestExec a
runFdPrim fn fd prim = do
    s <- lift get
    let fds = tsFDescs s
    case (I.lookup (fromIntegral fd) fds) of
        Nothing -> throwM $ mkIOError illegalOperationErrorType fn
                                Nothing (Just $ "<" ++ show fd ++ ">")
        Just desc -> prim s fds desc

-- N.B.: This will not work on pipes as it breaks the pipe!
readLinePrim :: Fd -> FdPrim (TestExec (Bool, L.ByteString))
readLinePrim fd s fds desc = do
    (eof, line, rest) <- breakLine <$> fdReadAll desc
    let desc' = contentFDesc rest
    lift $ put s { tsFDescs = I.insert (fromIntegral fd) desc' fds }
    return (eof, line)
  where
    breakLine b = let (pre, post) = L.break (== w8nl) b in
        maybe (True, pre, post) (\(nl, rest) -> (False, L.snoc pre nl, rest))
            $ L.uncons post
    w8nl = fromIntegral $ fromEnum '\n'

updateFileSystem :: FileSystem -> TestExec ()
updateFileSystem fs = lift $ modify (\s -> s { tsFileSystem = fs })

updateTestState :: TestState -> TestExec ()
updateTestState s = lift . put $ s

openFDesc :: FDesc -> TestExec Fd
openFDesc fdesc = do
    s <- lift get
    let fd = freeDesc 0 $ tsFDescs s
    lift $ put s { tsFDescs = I.insert fd fdesc $ tsFDescs s}
    return $ fromIntegral fd
  where
    freeDesc fd fds = if I.member fd fds then freeDesc (fd + 1) fds else fd

openFile :: DirPath -> Name -> TestExec Fd
openFile dp n = do
    fs <- lift $ gets tsFileSystem
    case fsItemEntry fs dp n of
        Just (FileItem i) ->
            case I.lookup i $ fsStore fs of
                Just (INode itype _) -> openFDesc $ iNodeFDesc i itype
                _ -> return (-1) -- TODO: should never happen
        _ -> return (-1) -- TODO: should never happen

fileMustExist :: String -> FilePath -> FileSystem -> DirPath -> Name -> TestExec ()
fileMustExist fn fp fs dp n =
    unless (fsFileExists fs dp n) $ raise doesNotExistErrorType fn fp

fileMustNotExist :: String -> FilePath -> FileSystem -> DirPath -> Name -> TestExec ()
fileMustNotExist fn fp fs dp n =
    when (fsFileExists fs dp n) $ raise alreadyExistsErrorType fn fp

directoryMustExist :: String -> FilePath -> FileSystem -> DirPath -> TestExec ()
directoryMustExist fn fp fs dp =
    unless (fsDirectoryExists fs dp) $ raise doesNotExistErrorType fn fp

directoryMustNotExist :: String -> FilePath -> FileSystem -> DirPath -> TestExec ()
directoryMustNotExist fn fp fs dp =
    when (fsDirectoryExists fs dp) $ raise alreadyExistsErrorType fn fp

raise :: IOErrorType -> String -> FilePath -> TestExec a
raise iot fn fp = throwM $ mkIOError iot fn Nothing (Just fp)