text:
const async = require('async');

const jsutil = require('arsenal').jsutil;

const config = require('../Config');
const BackbeatProducer = require('../BackbeatProducer');
const ReplicationQueuePopulator =
    require('../../extensions/replication/ReplicationQueuePopulator');

const { metricsExtension, metricsTypeQueued } =
    require('../../extensions/replication/constants');
const { transformKey } = require('../util/entry');

class LogReader {

    /**
     * Create a log reader object to populate kafka topics from a
     * single log source (e.g. one raft session)
     *
     * @constructor
     * @param {Object} params - constructor params
     * @param {Object} params.zkClient - zookeeper client object
     * @param {Object} params.kafkaConfig - kafka configuration object
     * @param {Object} [params.logConsumer] - log consumer object
     * @param {function} params.logConsumer.readRecords - function
     *   that fetches records from the log, called by LogReader
     * @param {String} params.logId - log source unique identifier
     * @param {Logger} params.logger - logger object
     * @param {QueuePopulatorExtension[]} params.extensions - array of
     *   queue populator extension modules
     * @param {MetricsProducer} params.metricsProducer - instance of metrics
     *   producer
     * @param {MetricsHandler} params.metricsHandler - instance of metrics
     *   handler
     * @param {ZkMetricsHandler} params.zkMetricsHandler - instance of zookeeper
     *   metrics handler
     */
    constructor(params) {
        this.zkClient = params.zkClient;
        this.kafkaConfig = params.kafkaConfig;
        this.logConsumer = params.logConsumer;
        this.pathToLogOffset = `${config.queuePopulator.zookeeperPath}/` +
            `logState/${params.logId}/logOffset`;
        this.logOffset = null;
        this.log = params.logger;
        this._producers = {};
        this._extensions = params.extensions;
        this._mProducer = params.metricsProducer;

        // internal variable to carry over a tailable cursor across batches
        this._openLog = null;
        this._metricsHandler = params.metricsHandler;
        // TODO: use a common handler for zk metrics from all extensions
        this._zkMetricsHandler = params.zkMetricsHandler;
    }

    _setEntryBatch(entryBatch) {
        this._extensions.forEach(ext => ext.setBatch(entryBatch));
    }

    _unsetEntryBatch() {
        this._extensions.forEach(ext => ext.unsetBatch());
    }

    setLogConsumer(logConsumer) {
        this.logConsumer = logConsumer;
    }

    /**
     * prepare the log reader before starting to populate entries
     *
     * This function may be overriden by subclasses, if source log
     * initialization is needed, in which case they must still call
     * LogReader.setup().
     *
     * @param {function} done - callback function
     * @return {undefined}
     */
    setup(done) {
        this.log.debug('setting up log source',
            {
                method: 'LogReader.setup',
                logSource: this.getLogInfo(),
            });
        this._readLogOffset((err, offset) => {
            if (err) {
                this.log.error('log source setup failed',
                    {
                        method: 'LogReader.setup',
                        logSource: this.getLogInfo(),
                    });
                return done(err);
            }
            this.logOffset = offset;
            this.log.info('log reader is ready to populate backbeat queue(s)',
                {
                    logSource: this.getLogInfo(),
                    logOffset: this.logOffset
                });
            return done();
        });
    }

    /**
     * close the log reader, free any resources opened during the
     * LogReader lifetime
     *
     * @param {function} cb - callback function
     * @return {undefined}
     */
    close(cb) {
        async.each(
            Object.values(this._producers),
            (producer, done) => producer.close(done),
            cb);
    }

    /**
     * get the next offset to fetch from source log (aka. log sequence
     * number)
     *
     * @return {string} the next log offset to fetch
     */
    getLogOffset() {
        return this.logOffset;
    }

    _readLogOffset(done) {
        const pathToLogOffset = this.pathToLogOffset;
        this.zkClient.getData(pathToLogOffset, (err, data) => {
            if (err) {
                this._updateZkMetrics('read', 'error');
                if (err.name !== 'NO_NODE') {
                    this.log.error(
                        'Could not fetch log offset',
                        {
                            method: 'LogReader._readLogOffset',
                            error: err,
                        });
                    return done(err);
                }
                return this.zkClient.mkdirp(pathToLogOffset, err => {
                    if (err) {
                        this.log.error(
                            'Could not pre-create path in zookeeper',
                            {
                                method: 'LogReader._readLogOffset',
                                zkPath: pathToLogOffset,
                                error: err,
                            });
                        this._updateZkMetrics('write', 'error');
                        return done(err);
                    }
                    this._updateZkMetrics('write', 'success');
                    return this._initializeLogOffset(done);
                });
            }
            if (data) {
                this._updateZkMetrics('read', 'success');
                let logOffset;
                if (config.queuePopulator.logSource === 'mongo') {
                    logOffset = data.toString();
                } else {
                    const logOffsetNumber = Number.parseInt(data, 10);
                    if (Number.isNaN(logOffsetNumber)) {
                        this.log.error(
                            'invalid stored log offset',
                            {
                                method: 'LogReader._readLogOffset',
                                zkPath: pathToLogOffset,
                                logOffset: data.toString()
                            });
                        return done(null, 1);
                    }
                    logOffset = logOffsetNumber.toString();
                }
                this.log.debug(
                    'fetched current log offset successfully',
                    {
                        method: 'LogReader._readLogOffset',
                        zkPath: pathToLogOffset,
                        logOffset,
                    });
                return done(null, logOffset);
            }
            return this._initializeLogOffset(done);
        });
    }

    _initializeLogOffset(done) {
        // TODO start at latest log offset on non-bucketd backends (mongodb, dmd)
        if (config.queuePopulator.logSource !== 'bucketd') {
            return done(null, 1);
        }
        const pathToLogOffset = this.pathToLogOffset;
        this.log.debug('initializing log offset', {
            method: 'LogReader._initializeLogOffset',
            zkPath: pathToLogOffset,
        });
        return this.logConsumer.readRecords({ limit: 1 }, (err, res) => {
            if (err) {
                // FIXME: getRaftLog metadata route returns 500 when
                // its cache does not contain the queried raft
                // session. For the sake of simplicity, in order to
                // allow the populator to make progress, we choose to
                // accept errors fetching the current offset during
                // setup phase and fallback to starting from offset
                // 1. It would be better to have metadata return
                // special success statuses in such case.
                this.log.warn(
                    'error reading initial log offset, ' +
                        'default to initial offset 1', {
                            method: 'LogReader._initializeLogOffset',
                            zkPath: pathToLogOffset,
                            logOffset: 1,
                            error: err,
                        });
                return done(null, 1);
            }
            const logOffset = res.info.cseq + 1;
            this.log.info('starting after latest log sequence', {
                method: 'LogReader._initializeLogOffset',
                zkPath: pathToLogOffset,
                logOffset,
            });
            return done(null, logOffset);
        });
    }

    _writeLogOffset(logger, done) {
        const pathToLogOffset = this.pathToLogOffset;
        const offsetString = this.logOffset.toString();
        this.zkClient.setData(
            pathToLogOffset,
            Buffer.from(offsetString), -1,
            err => {
                if (err) {
                    logger.error(
                        'error saving log offset',
                        {
                            method: 'LogReader._writeLogOffset',
                            zkPath: pathToLogOffset,
                            logOffset: this.logOffset,
                        });
                    this._updateZkMetrics('write', 'error');
                    return done(err);
                }
                this._updateZkMetrics('write', 'success');
                logger.debug(
                    'saved log offset',
                    {
                        method: 'LogReader._writeLogOffset',
                        zkPath: pathToLogOffset,
                        logOffset: this.logOffset,
                    });
                return done();
            }
        );
    }

    /**
     * Process log entries, up to the maximum defined in params or
     * until the timeout is reached waiting for new entries to come
     * (if tailable oplog)
     *
     * @param {Object} [params] - parameters object
     * @param {Number} [params.maxRead] - max number of records to process
     *   from the log. Records may contain multiple entries and all entries
     *   are not queued, so the number of queued entries is not directly
     *   related to this number.
     * @param {Number} [params.timeoutMs] - timeout after which the
     *   batch will be stopped if still running (default 10000ms)
     * @param {function} done - callback when done processing the
     *   entries - done(error) or done(null, {boolean} hasMoreLog:
     *   true if there is more log to read)
     * @return {undefined}
     */
    processLogEntries(params, done) {
        const batchState = {
            logRes: null,
            logStats: {
                nbLogRecordsRead: 0,
                nbLogEntriesRead: 0,
                hasMoreLog: false,
            },
            entriesToPublish: {},
            publishedEntries: {},
            currentRecords: [],
            maxRead: params.maxRead,
            startTime: Date.now(),
            timeoutMs: params.timeoutMs,
            logger: this.log.newRequestLogger(),
        };
        async.waterfall([
            next => this._processReadRecords(params, batchState, next),
            next => this._processPrepareEntries(batchState, next),
            next => this._processFilterEntries(batchState, next),
            next => this._processPublishEntries(batchState, next),
            next => this._processSaveLogOffset(batchState, next),
        ],
            err => {
                if (err) {
                    return done(err);
                }
                const queuedEntries = {};
                const { publishedEntries } = batchState;
                Object.keys(publishedEntries).forEach(topic => {
                    queuedEntries[topic] = publishedEntries[topic].length;
                });
                const stats = {
                    readRecords: batchState.logStats.nbLogRecordsRead,
                    readEntries: batchState.logStats.nbLogEntriesRead,
                    skippedRecords: batchState.logStats.skippedRecords,
                    hasMoreLog: batchState.logStats.hasMoreLog,
                    queuedEntries,
                };
                // Use heuristics to log when:
                // - at least one entry is pushed to any topic
                // - many records have been skipped (e.g. when starting up
                //   consumption from mongo oplog)
                // - the batch took a significant time to complete.
                const useInfoLevel =
                    Object.keys(stats.queuedEntries).length > 0 ||
                    stats.skippedRecords > 1000;
                const endLog = batchState.logger.end();
                const logFunc = (useInfoLevel ? endLog.info : endLog.debug)
                    .bind(endLog);
                logFunc('batch completed', {
                    stats,
                    logSource: this.getLogInfo(),
                    logOffset: this.getLogOffset(),
                });
                return done(null, stats.hasMoreLog);
            });
        return undefined;
    }

    /* eslint-disable no-param-reassign */

    _processReadRecords(params, batchState, done) {
        if (this._openLog) {
            // an open tailable cursor already exists: reuse it
            batchState.logRes = this._openLog;
            return done();
        }
        const { logger } = batchState;
        const readOptions = {};
        if (this.logOffset !== undefined) {
            readOptions.startSeq = this.logOffset;
        }
        if (params && params.maxRead !== undefined) {
            // only has effect for non-tailable oplog
            readOptions.limit = params.maxRead;
        }
        logger.debug('reading records', { readOptions });
        return this.logConsumer.readRecords(readOptions, (err, res) => {
            if (err) {
                logger.error(
                    'error while reading log records',
                    {
                        method: 'LogReader._processReadRecords',
                        params, error: err,
                    });
                return done(err);
            }
            logger.debug(
                'readRecords callback',
                {
                    method: 'LogReader._processReadRecords',
                    params
                });
            batchState.logRes = res;
            if (res.tailable) {
                // carry tailable cursor over for future batches
                this._openLog = res;
            }
            return done();
        });
    }

    _processPrepareEntries(batchState, done) {
        const { logRes, logStats, logger } = batchState;

        // for raft log only
        if (logRes.info && logRes.info.start === null) {
            return done(null);
        }

        let shipBatchCb;
        const dataEventHandler = record => {
            logger.debug('received log data', {
                nbEntries: record.entries.length,
                timestamp: record.timestamp,
            });
            logStats.nbLogRecordsRead += 1;

            if (record.timestamp) {
                const timestamp = new Date(record.timestamp).getTime() / 1000;
                this._metricsHandler.logTimestamp(this.getMetricLabels(), timestamp);
            }
            batchState.currentRecords.push(record);
            // Pause tailable streams when reaching the record batch
            // limit, as those streams do not emit 'end' events but
            // continuously send 'data' events as they come.
            if (logRes.tailable &&
                logStats.nbLogRecordsRead >= batchState.maxRead) {
                logger.debug('ending batch', {
                    method: 'LogReader._processPrepareEntries',
                    reason: 'limit on number of read records reached',
                    readRecords: logStats.nbLogRecordsRead,
                });
                return shipBatchCb();
            }
            return undefined;
        };
        const errorEventHandler = err => {
            logger.error('error fetching entries from log', {
                method: 'LogReader._processPrepareEntries',
                error: err,
            });
            return shipBatchCb(err);
        };
        const endEventHandler = () => {
            logger.debug('ending record stream', {
                method: 'LogReader._processPrepareEntries',
            });
            return shipBatchCb();
        };
        logRes.log.on('data', dataEventHandler);
        logRes.log.on('error', errorEventHandler);
        logRes.log.on('end', endEventHandler);

        if (logRes.tailable) {
            //
            // For tailable oplog, set an interval check to timely end
            // and ship the current batch "timeoutMs" after the
            // beginning of the batch.
            //
            // This should guarantee regular updates to the stored
            // offset in zookeeper, while allowing a batch enough time
            // to maximize its rate of consumption of log messages
            // (deemed useful to reduce startup time).
            //
            const checker = setInterval(() => {
                const now = Date.now();
                if (now >= batchState.startTime + batchState.timeoutMs) {
                    logger.debug('ending batch', {
                        method: 'LogReader._processPrepareEntries',
                        reason: 'batch timeout reached',
                        readRecords: logStats.nbLogRecordsRead,
                    });
                    shipBatchCb();
                }
            }, 1000);
            shipBatchCb = jsutil.once(err => {
                logRes.log.pause();
                logRes.log.removeListener('data', dataEventHandler);
                logRes.log.removeListener('error', errorEventHandler);
                logRes.log.removeListener('end', endEventHandler);
                clearInterval(checker);
                done(err);
            });
        } else {
            shipBatchCb = jsutil.once(done);
            // for raft log
            logRes.log.on('info', info => {
                logger.debug('received record stream "info" event', {
                    method: 'LogReader._processPrepareEntries',
                    info,
                });
                logRes.info = info;
            });
        }
        if (logRes.tailable && logRes.log.isPaused()) {
            logger.debug('resuming tailable cursor', {
                method: 'LogReader._processPrepareEntries',
            });
            logRes.log.resume();
        }
        if (logRes.log.getSkipCount) {
            logStats.initialSkipCount = logRes.log.getSkipCount();
        }
        return undefined;
    }

    _processLogEntry(batchState, record, entry, cb) {
        function _executeFilter(ext, entry, cb) {
            if (typeof ext.filterAsync === 'function') {
                ext.filterAsync(entry, cb);
            } else {
                ext.filter(entry);
                process.nextTick(cb);
            }
        }
        async.eachSeries(this._extensions, (ext, next) => {
            if (entry.value === undefined) {
                return next();
            }
            const entryToFilter = {
                type: entry.type,
                bucket: record.db,
                // removing the v1 metadata prefix if it exists
                key: transformKey(entry.key),
                value: entry.value,
                logReader: this,
            };
            return _executeFilter(ext, entryToFilter, next);
        }, cb);
    }

    _filterEntries(batchState, record, cb) {
        const { logStats } = batchState;

        return async.eachSeries(record.entries, (entry, next) => {
            logStats.nbLogEntriesRead += 1;
            return this._processLogEntry(batchState, record, entry, next);
        }, cb);
    }

    _processFilterEntry(batchState, record, done) {
        if (!record || !record.entries) {
            return done();
        }
        const { entriesToPublish } = batchState;
        this._setEntryBatch(entriesToPublish);
        return this._filterEntries(batchState, record, err => {
            this._unsetEntryBatch();
            if (err) {
                this.log.error('error filtering entries from log', {
                    method: 'LogReader._processFilterEntries',
                    error: err,
                });
                return done(err);
            }
            return done();
        });
    }

    _processFilterEntries(batchState, done) {
        const { currentRecords } = batchState;
        if (!currentRecords || !currentRecords.length) {
            return done();
        }
        return async.eachSeries(currentRecords,
            (rec, next) => this._processFilterEntry(batchState, rec, next),
            err => {
                if (err) {
                    this.log.error('error filtering entries from log', {
                        method: 'LogReader._processFilterEntries',
                        error: err,
                    });
                    return done(err);
                }
                return done();
            }
        );
    }

    _setupProducer(topic, done) {
        if (this._producers[topic] !== undefined) {
            return process.nextTick(done);
        }
        const producer = new BackbeatProducer({
            kafka: { hosts: this.kafkaConfig.hosts },
            topic,
        });
        producer.once('error', done);
        producer.once('ready', () => {
            this.log.debug('producer is ready',
                {
                    kafkaConfig: this.kafkaConfig,
                    topic,
                });
            producer.removeAllListeners('error');
            producer.on('error', err => {
                this.log.error('error from backbeat producer',
                    { topic, error: err });
            });
            this._producers[topic] = producer;
            done();
        });
        return undefined;
    }

    _processPublishEntries(batchState, done) {
        const { entriesToPublish, logRes, logStats, logger } = batchState;

        // for raft log only
        if (logRes.info && logRes.info.start === null) {
            return done();
        }

        if (logRes.log.getOffset) {
            batchState.nextLogOffset = logRes.log.getOffset();
        } else {
            batchState.nextLogOffset =
                logRes.info.start + logStats.nbLogRecordsRead;
        }
        if (logStats.initialSkipCount !== undefined) {
            const finalSkipCount = logRes.log.getSkipCount();
            logStats.skippedRecords =
                finalSkipCount - logStats.initialSkipCount;
        }
        return async.each(Object.keys(entriesToPublish), (topic, done) => {
            const topicEntries = entriesToPublish[topic];
            if (topicEntries.length === 0) {
                return done();
            }
            return async.series([
                done => this._setupProducer(topic, done),
                done => this._producers[topic].send(topicEntries, done),
            ], err => {
                if (err) {
                    logger.error(
                        'error publishing entries from log to topic',
                        {
                            method: 'LogReader._processPublishEntries',
                            topic,
                            entryCount: topicEntries.length,
                            error: err,
                        }
                    );
                    const labels = Object.assign({},
                        this.getMetricLabels(),
                        { publishStatus: 'FAILURE' }
                    );
                    this._metricsHandler.messages(labels, topicEntries.length);
                    return done(err);
                }
                logger.debug('entries published successfully to topic',
                    {
                        method: 'LogReader._processPublishEntries',
                        topic, entryCount: topicEntries.length
                    });
                batchState.publishedEntries[topic] = topicEntries;
                const labels = Object.assign({},
                    this.getMetricLabels(),
                    { publishStatus: 'SUCCESS' }
                );
                this._metricsHandler.messages(labels, topicEntries.length);
                return done();
            });
        }, err => {
            // TODO: On error, produce error metrics
            if (err) {
                return done(err);
            }
            // Find the CRR Class extension
            const crrExtension = this._extensions.find(ext => (
                ext instanceof ReplicationQueuePopulator
            ));
            if (crrExtension) {
                const extMetrics = crrExtension.getAndResetMetrics();
                if (Object.keys(extMetrics).length > 0) {
                    this._mProducer.publishMetrics(extMetrics,
                        metricsTypeQueued, metricsExtension, () => { });
                }
            }
            return done();
        });
    }

    _processSaveLogOffset(batchState, done) {
        const { logRes, nextLogOffset, logger } = batchState;
        if (nextLogOffset !== undefined &&
            nextLogOffset !== this.logOffset &&
            (!logRes.log.reachedUnpublishedListing ||
             logRes.log.reachedUnpublishedListing())) {

            this.logOffset = nextLogOffset;

            // Skip metrics if we are not using Raft backend
            if (logRes.info) {
                const logSize = logRes.info.cseq || logRes.info.end;
                this._metricsHandler.logReadOffset(this.getMetricLabels(), this.logOffset);
                this._metricsHandler.logSize(this.getMetricLabels(), logSize);
            }

            return this._writeLogOffset(logger, done);
        }
        return process.nextTick(() => done());
    }

    _updateZkMetrics(op, status) {
        if (this._zkMetricsHandler && this._zkMetricsHandler.onZookeeperOp) {
            this._zkMetricsHandler.onZookeeperOp(op, status);
        }
    }

    /* eslint-enable no-param-reassign */

    /**
     * return an object containing useful info about the log
     * source. The default implementation returns an empty object,
     * subclasses may override to provide source-specific info.
     *
     * @return {object} log info object
     */
    getLogInfo() {
        return {};
    }

    /**
     * return an object to include as part of metric labels
     * @return {object} labels to include
     */
    getMetricLabels() {
        return {};
    }

    /**
     * Return an object of the current status of each producer.
     * @returns {Object<string, Boolean>} map of producer statuses
     */
    getProducerStatus() {
        const statuses = {};
        Object.keys(this._producers).forEach(topic => {
            statuses[topic] = this._producers[topic].isReady();
        });
        return statuses;
    }
}

module.exports = LogReader;


text:
<?php

// Call Zend_View_Helper_CycleTest::main() if this source file is executed directly.
if (! defined("PHPUnit_MAIN_METHOD")) {
    define("PHPUnit_MAIN_METHOD", "Zend_View_Helper_CycleTest::main");
}

/** Zend_View_Helper_Cycle */
// require_once 'Zend/View/Helper/Cycle.php';

/**
 * Test class for Zend_View_Helper_Cycle.
 *
 * @category   Zend
 * @package    Zend_View
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @group      Zend_View
 * @group      Zend_View_Helper
 */
class Zend_View_Helper_CycleTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Zend_View_Helper_Cycle
     */
    public $helper;

    /**
     * Runs the test methods of this class.
     *
     * @return void
     */
    public static function main()
    {
        $suite = new PHPUnit_Framework_TestSuite("Zend_View_Helper_CycleTest");
        $result = PHPUnit_TextUI_TestRunner::run($suite);
    }

    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @return void
     */
    public function setUp()
    {
        $this->helper = new Zend_View_Helper_Cycle();
    }

    /**
     * Tears down the fixture, for example, close a network connection.
     * This method is called after a test is executed.
     *
     * @return void
     */
    public function tearDown()
    {
        unset($this->helper);
    }

    public function testCycleMethodReturnsObjectInstance()
    {
        $cycle = $this->helper->cycle();
        $this->assertTrue($cycle instanceof Zend_View_Helper_Cycle);
    }

    public function testAssignAndGetValues()
    {
        $this->helper->assign(array('a', 1, 'asd'));
        $this->assertEquals(array('a', 1, 'asd'), $this->helper->getAll());
    }

    public function testCycleMethod()
    {
        $this->helper->cycle(array('a', 1, 'asd'));
        $this->assertEquals(array('a', 1, 'asd'), $this->helper->getAll());
    }

    public function testToString()
    {
        $this->helper->cycle(array('a', 1, 'asd'));
        $this->assertEquals('a', (string) $this->helper->toString());
    }

    public function testNextValue()
    {
        $this->helper->assign(array('a', 1, 3));
        $this->assertEquals('a', (string) $this->helper->next());
        $this->assertEquals(1, (string) $this->helper->next());
        $this->assertEquals(3, (string) $this->helper->next());
        $this->assertEquals('a', (string) $this->helper->next());
        $this->assertEquals(1, (string) $this->helper->next());
    }

    public function testPrevValue()
    {
        $this->helper->assign(array(4, 1, 3));
        $this->assertEquals(3, (string) $this->helper->prev());
        $this->assertEquals(1, (string) $this->helper->prev());
        $this->assertEquals(4, (string) $this->helper->prev());
        $this->assertEquals(3, (string) $this->helper->prev());
        $this->assertEquals(1, (string) $this->helper->prev());
    }

    public function testRewind()
    {
        $this->helper->assign(array(5, 8, 3));
        $this->assertEquals(5, (string) $this->helper->next());
        $this->assertEquals(8, (string) $this->helper->next());
        $this->helper->rewind();
        $this->assertEquals(5, (string) $this->helper->next());
        $this->assertEquals(8, (string) $this->helper->next());
    }

    public function testMixedMethods()
    {
        $this->helper->assign(array(5, 8, 3));
        $this->assertEquals(5, (string) $this->helper->next());
        $this->assertEquals(5, (string) $this->helper->current());
        $this->assertEquals(8, (string) $this->helper->next());
        $this->assertEquals(5, (string) $this->helper->prev());
    }

    public function testTwoCycles()
    {
        $this->helper->assign(array(5, 8, 3));
        $this->assertEquals(5, (string) $this->helper->next());
        $this->assertEquals(2, (string) $this->helper->cycle(array(2,38,1),'cycle2')->next());
        $this->assertEquals(8, (string) $this->helper->cycle()->next());
        $this->assertEquals(38, (string) $this->helper->setName('cycle2')->next());
    }

    public function testTwoCyclesInLoop()
    {
        $expected = array(5,4,2,3);
        $expected2 = array(7,34,8,6);
        for($i=0;$i<4;$i++) {
          $this->assertEquals($expected[$i], (string) $this->helper->cycle($expected)->next());
          $this->assertEquals($expected2[$i], (string) $this->helper->cycle($expected2,'cycle2')->next());
        }
    }

}
// Call Zend_View_Helper_CycleTest::main() if this source file is executed directly.
if (PHPUnit_MAIN_METHOD == "Zend_View_Helper_CycleTest::main") {
    Zend_View_Helper_CycleTest::main();
}

redpajama_set_name: RedPajamaGithub


text:
//
//  BRRelutionIBeaconMessageActionMapper.h
//  BlueRangeSDK
//
// Copyright (c) 2016-2017, M-Way Solutions GmbH
// All rights reserved.
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//

#import <Foundation/Foundation.h>
#import "BRIBeaconMessageActionMapper.h"

@protocol BRITracer;
@class BRRelution;

@interface BRRelutionIBeaconMessageActionMapper : NSObject<BRIBeaconMessageActionMapper> {
    BRRelution* _relution;
}

- (id) initWithRelution: (BRRelution*) relution;
- /* override */ (BRRelutionActionInformation*) getBeaconActionInformationForMessage: (BRIBeaconMessage*) message;
- /* override */ (BOOL) isAvailable;

@end


text:
using System;
using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.Practices.Prism.Mvvm.Interfaces;
using Microsoft.Reactive.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Services.Interfaces;
using ShareLink.Models;
using ShareLink.Services;
using ShareLink.Services.Interfaces;
using ShareLink.Tests.Mocks;
using ShareLink.ViewModels.ViewModels;
using Utilities.Functional;

namespace ShareLink.Tests.ViewModels
{

    [TestClass]
    public class TestMainPageViewModel
    {
        private IWindowService _windowService;
        private IDataTransferService _dataTransferService;
        private IClipboardService _clipboardService;
        private IHttpService _httpService;
        private ISchedulerProvider _schedulerProvider;
        private readonly TestScheduler _testScheduler = new TestScheduler();
        private ITextToSpeechService _textToSpeechService;
        private ApplicationSettingsService _applicationSettingsService;
        private ISettingsService _uiSettingsService;
        private IShareDataRepository _shareDataRepository;
        private INavigationService _navigationService;

        [TestInitialize]
        public void Initialize()
        {
            _windowService = A.Fake<IWindowService>();
            _dataTransferService = A.Fake<IDataTransferService>();
            _clipboardService = A.Fake<IClipboardService>();
            _httpService = A.Fake<IHttpService>();
            _schedulerProvider = A.Fake<ISchedulerProvider>();
            _textToSpeechService = A.Fake<ITextToSpeechService>();
            _applicationSettingsService = new ApplicationSettingsService(new MockApplicationDataContainer());
            _uiSettingsService = A.Fake<ISettingsService>();
            _shareDataRepository = A.Fake<IShareDataRepository>();
            _navigationService = A.Fake<INavigationService>();

            A.CallTo(() => _schedulerProvider.Default).Returns(_testScheduler);
        }

        [TestCleanup]
        public void Cleanup()
        {
        }

        private MainPageViewModel CreateViewModel()
        {
            return new MainPageViewModel(_windowService, _dataTransferService, _clipboardService,
                _httpService, _schedulerProvider, _textToSpeechService, _applicationSettingsService,
                _uiSettingsService, _navigationService);
        }

        [TestMethod]
        public void DefaultTextValue()
        {
            var viewModel = CreateViewModel();

            Assert.AreEqual(null, viewModel.Text.Value);
        }

        [TestMethod]
        public void CopyClipboardTextWhenApplicationBecomesVisible()
        {
            const string clipboardText = "SomeText";
            var visibilitySubject = new Subject<bool>();
            A.CallTo(() => _clipboardService.GetTextAsync(A<CancellationToken>.Ignored)).Returns(Task.FromResult(Option<string>.AsOption(clipboardText)));
            A.CallTo(() => _windowService.IsVisibleObservable).Returns(visibilitySubject);
            var viewModel = CreateViewModel();

            visibilitySubject.OnNext(true);

            Assert.AreEqual(clipboardText, viewModel.Text.Value);
        }

        [TestMethod]
        public void SelectAllIsNotTriggeredByDefault()
        {
            var viewModel = CreateViewModel();
            bool selectAllWasTriggered = false;
            viewModel.SelectAllTextTrigger.Subscribe(_ => selectAllWasTriggered = true);

            _testScheduler.AdvanceBy(TimeSpan.FromDays(10).Ticks);

            Assert.IsFalse(selectAllWasTriggered);
        }

        [TestMethod]
        public void SelectAllIsNotTriggeredInstantlyAfterVisibilityChange()
        {
            var visibilitySubject = new Subject<bool>();
            A.CallTo(() => _windowService.IsVisibleObservable).Returns(visibilitySubject);
            var viewModel = CreateViewModel();
            bool selectAllWasTriggered = false;
            viewModel.SelectAllTextTrigger.Subscribe(_ => selectAllWasTriggered = true);

            visibilitySubject.OnNext(true);

            Assert.IsFalse(selectAllWasTriggered);
        }

        [TestMethod]
        public void TriggerTextSelectionAfterDelayWhenCopiedTextFromClipboard()
        {
            var visibilitySubject = new Subject<bool>();
            A.CallTo(() => _windowService.IsVisibleObservable).Returns(visibilitySubject);
            var viewModel = CreateViewModel();
            bool selectAllWasTriggered = false;
            viewModel.SelectAllTextTrigger.Subscribe(_ => selectAllWasTriggered = true);

            visibilitySubject.OnNext(true);
            _testScheduler.AdvanceBy(TimeSpan.FromMilliseconds(300).Ticks);

            Assert.IsTrue(selectAllWasTriggered);
        }

        [TestMethod]
        public void CannotExecuteShareCommandIfTextIsNotValidUri()
        {
            var viewModel = CreateViewModel();

            viewModel.Text.Value = "#$%^&*(";

            Assert.AreEqual(false, viewModel.ShareCommand.CanExecute());
        }

        [TestMethod]
        public void CanExecuteShareCommandIfTextCanBeChangedToValidUri()
        {
            var viewModel = CreateViewModel();

            viewModel.Text.Value = "test";

            Assert.AreEqual(true, viewModel.ShareCommand.CanExecute());
        }

        [TestMethod]
        public void CannotPressEnterCommandIfTextIsNotValidUri()
        {
            var viewModel = CreateViewModel();

            viewModel.Text.Value = "#$%^&*(";

            Assert.AreEqual(false, viewModel.KeyPressedCommand.CanExecute());
        }

        [TestMethod]
        public void CanPressEnterCommandIfTextCanBeChangedToValidUri()
        {
            var viewModel = CreateViewModel();
            viewModel.Text.Value = "test";

            Assert.AreEqual(true, viewModel.KeyPressedCommand.CanExecute());
        }

        [TestMethod]
        public void TriggerShareWhenExecutingShare()
        {
            var viewModel = CreateViewModel();
            viewModel.Text.Value = "test";

            viewModel.ShareCommand.Execute();

            A.CallTo(() => _dataTransferService.Share(A<ShareData>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
        }

        [TestMethod]
        [Ignore] // verify title
        public void ResolveTitleOfPage()
        {
            const string pageTitle = "SomeTitle";
            A.CallTo(() => _httpService.GetPageTitleAsync(A<Uri>.Ignored, A<CancellationToken>.Ignored)).Returns(Task.FromResult(Option<string>.AsOption(pageTitle) ));
            var viewModel = CreateViewModel();
            viewModel.Text.Value = "test";

            viewModel.ShareCommand.Execute();

            A.CallTo(() => _dataTransferService.Share(A<ShareData>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
        }

        [TestMethod]
        public void TappingSettingsButtonShowsSettings()
        {
            var viewModel = CreateViewModel();

            viewModel.SettingsCommand.Execute(null);

            A.CallTo(() => _uiSettingsService.ShowSettings()).MustHaveHappened(Repeated.Exactly.Once);
        }

        [TestMethod]
        public void StartingSharingStartsProgress()
        {
            var viewModel = CreateViewModel();
            viewModel.Text.Value = "test";
            A.CallTo(() => _httpService.GetPageTitleAsync(A<Uri>.Ignored, A<CancellationToken>.Ignored)).Returns(Task.FromResult(Option<string>.AsOption("pageTitle")));
            bool progressChangedToTrue = false;
            viewModel.IsInProgress.Subscribe(isInProgress => progressChangedToTrue |= isInProgress);

            viewModel.ShareCommand.Execute();

            Assert.AreEqual(true, progressChangedToTrue);
        }

    }
}


text:
package integration_tests

import (
	"fmt"
	"testing"

	sdk "github.com/ionos-cloud/ionos-enterprise-sdk-go/v5"
	"github.com/stretchr/testify/assert"
)

var lanid string
var lanfailoverid string
var lannicsrvid string
var lannicid string
var ipblockID2 string

func TestCreateLan(t *testing.T) {
	fmt.Println("Lan tests")
	c := setupTestEnv()
	onceLan.Do(createDataCenter)

	var request = sdk.Lan{
		Properties: sdk.LanProperties{
			Public: true,
			Name:   "GO SDK Test",
		},
	}

	lan, err := c.CreateLan(dataCenter.ID, request)
	if err != nil {
		t.Error(err)
	}

	err = c.WaitTillProvisioned(lan.Headers.Get("Location"))
	if err != nil {
		t.Error(err)
	}

	lanid = lan.ID

	assert.Equal(t, lan.PBType, "lan")
	assert.Equal(t, lan.Properties.Name, "GO SDK Test")
	assert.True(t, lan.Properties.Public)
}

func TestCreateLanFailure(t *testing.T) {
	c := setupTestEnv()
	var request = sdk.Lan{
		Properties: sdk.LanProperties{
			Public: true,
		},
	}
	_, err := c.CreateLan("00000000-0000-0000-0000-000000000000", request)
	assert.NotNil(t, err)
}

func TestCreateCompositeLan(t *testing.T) {
	c := setupTestEnv()
	onceLan.Do(createDataCenter)
	onceLanServer.Do(createCompositeServerFW)

	var obj = sdk.IPBlock{
		Properties: sdk.IPBlockProperties{
			Name:     "test",
			Size:     1,
			Location: "us/las",
		},
	}

	ipResponse, err := c.ReserveIPBlock(obj)
	ipblockID2 = ipResponse.ID

	lannicsrvid = nic.ID

	var nicRequest = sdk.Nic{
		Properties: &sdk.NicProperties{
			Lan:  1,
			Name: "Test NIC with failover",
			Nat:  boolAddr(false),
		},
	}

	nicResponse, err := c.CreateNic(dataCenter.ID, server.ID, nicRequest)
	if err != nil {
		t.Fatal(err)
	}
	err = c.WaitTillProvisioned(nicResponse.Headers.Get("Location"))
	if err != nil {
		t.Fatal(err)
	}

	lannicid = nicResponse.ID
	lanNics := sdk.LanNics{
		Items: []sdk.Nic{{ID: nic.ID}},
	}

	var request = sdk.Lan{
		Properties: sdk.LanProperties{
			Public: true,
			Name:   "GO SDK Test with failover",
		},
		Entities: &sdk.LanEntities{
			Nics: &lanNics,
		},
	}
	lan, err := c.CreateLan(dataCenter.ID, request)
	if err != nil {
		t.Fatal(err)
	}
	lanfailoverid = lan.ID

	err = c.WaitTillProvisioned(lan.Headers.Get("Location"))
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, lan.PBType, "lan")
	assert.Equal(t, lan.Properties.Name, "GO SDK Test with failover")
	assert.True(t, lan.Properties.Public)
}

func TestListLans(t *testing.T) {
	c := setupTestEnv()
	onceLan.Do(createDataCenter)
	onceLanServer.Do(createCompositeServerFW)
	lans, err := c.ListLans(dataCenter.ID)

	if err != nil {
		t.Error(err)
	}
	assert.True(t, len(lans.Items) > 0)
}

func TestGetLan(t *testing.T) {
	c := setupTestEnv()
	onceLan.Do(createDataCenter)
	onceLanLan.Do(createLan)
	lan, err := c.GetLan(dataCenter.ID, lan.ID)
	if err != nil {
		t.Error(err)
	}

	assert.Equal(t, lan.ID, lan.ID)
	assert.Equal(t, lan.PBType, "lan")
}

func TestUpdateLan(t *testing.T) {
	c := setupTestEnv()
	onceLan.Do(createDataCenter)
	onceLanLan.Do(createLan)
	obj := sdk.LanProperties{
		Name: "newName",
	}

	lan, err := c.UpdateLan(dataCenter.ID, lan.ID, obj)
	if err != nil {
		t.Error(err)
	}

	err = c.WaitTillProvisioned(lan.Headers.Get("Location"))
	if err != nil {
		t.Error(err)
	}
	assert.Equal(t, lan.ID, lan.ID)
	assert.Equal(t, lan.PBType, "lan")
	assert.Equal(t, lan.Properties.Name, obj.Name)
}

func TestDeleteLan(t *testing.T) {
	onceLan.Do(createDataCenter)
	onceLanLan.Do(createLan)
	c := setupTestEnv()
	_, err := c.DeleteLan(dataCenter.ID, lan.ID)
	if err != nil {
		t.Error(err)
	}
}

func TestLanCleanup(t *testing.T) {
	c := setupTestEnv()

	deleted, err := c.DeleteDatacenter(dataCenter.ID)
	if err != nil {
		t.Error(err)
	}
	c.WaitTillProvisioned(deleted.Get("Location"))

	c.ReleaseIPBlock(ipblockID2)
}


text:
#pragma once
#include <aws/devicefarm/DeviceFarm_EXPORTS.h>
#include <aws/core/utils/memory/stl/AWSString.h>

namespace Aws
{
namespace DeviceFarm
{
namespace Model
{
  enum class DeviceAttribute
  {
    NOT_SET,
    ARN,
    PLATFORM,
    FORM_FACTOR,
    MANUFACTURER,
    REMOTE_ACCESS_ENABLED,
    REMOTE_DEBUG_ENABLED,
    APPIUM_VERSION,
    INSTANCE_ARN,
    INSTANCE_LABELS,
    FLEET_TYPE,
    OS_VERSION,
    MODEL,
    AVAILABILITY
  };

namespace DeviceAttributeMapper
{
AWS_DEVICEFARM_API DeviceAttribute GetDeviceAttributeForName(const Aws::String& name);

AWS_DEVICEFARM_API Aws::String GetNameForDeviceAttribute(DeviceAttribute value);
} // namespace DeviceAttributeMapper
} // namespace Model
} // namespace DeviceFarm
} // namespace Aws


text:
import { isPresent } from 'angular2/src/facade/lang';
import { MapWrapper, StringMapWrapper } from 'angular2/src/facade/collection';
export { SetterFn, GetterFn, MethodFn } from './types';
export class Reflector {
    constructor(reflectionCapabilities) {
        this._typeInfo = MapWrapper.create();
        this._getters = MapWrapper.create();
        this._setters = MapWrapper.create();
        this._methods = MapWrapper.create();
        this.reflectionCapabilities = reflectionCapabilities;
    }
    registerType(type, typeInfo) {
        MapWrapper.set(this._typeInfo, type, typeInfo);
    }
    registerGetters(getters) {
        _mergeMaps(this._getters, getters);
    }
    registerSetters(setters) {
        _mergeMaps(this._setters, setters);
    }
    registerMethods(methods) {
        _mergeMaps(this._methods, methods);
    }
    factory(type) {
        if (this._containsTypeInfo(type)) {
            return this._getTypeInfoField(type, "factory", null);
        }
        else {
            return this.reflectionCapabilities.factory(type);
        }
    }
    parameters(typeOrFunc) {
        if (MapWrapper.contains(this._typeInfo, typeOrFunc)) {
            return this._getTypeInfoField(typeOrFunc, "parameters", []);
        }
        else {
            return this.reflectionCapabilities.parameters(typeOrFunc);
        }
    }
    annotations(typeOrFunc) {
        if (MapWrapper.contains(this._typeInfo, typeOrFunc)) {
            return this._getTypeInfoField(typeOrFunc, "annotations", []);
        }
        else {
            return this.reflectionCapabilities.annotations(typeOrFunc);
        }
    }
    interfaces(type) {
        if (MapWrapper.contains(this._typeInfo, type)) {
            return this._getTypeInfoField(type, "interfaces", []);
        }
        else {
            return this.reflectionCapabilities.interfaces(type);
        }
    }
    getter(name) {
        if (MapWrapper.contains(this._getters, name)) {
            return MapWrapper.get(this._getters, name);
        }
        else {
            return this.reflectionCapabilities.getter(name);
        }
    }
    setter(name) {
        if (MapWrapper.contains(this._setters, name)) {
            return MapWrapper.get(this._setters, name);
        }
        else {
            return this.reflectionCapabilities.setter(name);
        }
    }
    method(name) {
        if (MapWrapper.contains(this._methods, name)) {
            return MapWrapper.get(this._methods, name);
        }
        else {
            return this.reflectionCapabilities.method(name);
        }
    }
    _getTypeInfoField(typeOrFunc, key, defaultValue) {
        var res = MapWrapper.get(this._typeInfo, typeOrFunc)[key];
        return isPresent(res) ? res : defaultValue;
    }
    _containsTypeInfo(typeOrFunc) { return MapWrapper.contains(this._typeInfo, typeOrFunc); }
}
function _mergeMaps(target, config) {
    StringMapWrapper.forEach(config, (v, k) => MapWrapper.set(target, k, v));
}
//# sourceMappingURL=reflector.js.map


text:
package org.appng.core.repository;

import java.util.List;

import org.appng.core.domain.JobRecord;
import org.appng.persistence.repository.SearchRepository;
import org.springframework.data.jpa.repository.Query;

public interface JobRecordRepository extends SearchRepository<JobRecord, Integer> {

	List<JobRecord> findBySiteAndJobName(String site, String jobName);

	@Query("select distinct(j.application) from JobExecutionRecord j where j.site=?1 order by j.application")
	List<String> getDistinctApplications(String site);

	@Query("select distinct(j.jobName) from JobExecutionRecord j where j.site=?1 order by j.jobName")
	List<String> getDistinctJobNames(String site);

}


text:
MusicXtract
===========

Android application that extracts music from camera and images. Output is
in MusicXML 3.0 format.


text:
  Bilia est
       un village
       situé dans le département de Corse-du-Sud en Corse. Elle comptait 48 habitants en 2008.

Le nombre de logements, à Bilia, était réparti en 2011 en trois appartements et 55 maisons soit
 un marché plutôt équilibré.

À coté de Bilia sont localisées les communes de
Viggianello localisée à 7 km, 547 habitants,
Foce située à 8 km, 126 habitants,
Sartène localisée à 5 km, 3 096 habitants,
Grossa localisée à 2 km, 52 habitants,
Arbellara à 9 km, 132 habitants,
Belvédère-Campomoro à 7 km, 159 habitants,
 entre autres. De plus, Bilia est située à seulement cinq km de Propriano.

Si vous envisagez de demenager à Bilia, vous pourrez facilement trouver une maison à vendre.


text:
package org.elasticsearch.xpack.sql.client;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;

import static java.util.stream.Collectors.toMap;

public abstract class ObjectUtils {

    public static boolean isEmpty(int[] array) {
        return (array == null || array.length == 0);
    }

    public static boolean isEmpty(byte[] array) {
        return (array == null || array.length == 0);
    }

    public static boolean isEmpty(Object[] array) {
        return (array == null || array.length == 0);
    }

    public static <K, E extends Enum<E>> Map<K, E> mapEnum(Class<E> clazz, Function<E, K> mapper) {
        return Arrays.stream(clazz.getEnumConstants()).collect(toMap(mapper, Function.identity()));
    }
}


text:
<?php

namespace DvsaMotApi\Factory\Controller;

use Doctrine\ORM\EntityManager;
use DvsaDocument\Service\Document\DocumentService;
use DvsaEntities\Entity\CertificateReplacement;
use DvsaEntities\Entity\CertificateType;
use DvsaMotApi\Controller\CertificatePrintingController;
use DvsaMotApi\Service\CertificateCreationService;
use DvsaMotApi\Service\MotTestService;
use DvsaReport\Service\Report\LambdaReportService;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Class UserControllerFactory.
 */
class CertificatePrintingControllerFactory implements FactoryInterface
{
    /**
     * @param ServiceLocatorInterface $controllerManager
     *
     * @return CertificatePrintingController
     */
    public function createService(ServiceLocatorInterface $controllerManager)
    {
        return $this($controllerManager, CertificatePrintingController::class);
    }

    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        /** @var \Doctrine\ORM\EntityManager */
        $entityManager = $container->get(EntityManager::class);

        /* @var MotTestService */
        $motTestService = $container->get('MotTestService');

        /* @var DocumentService $documentService */
        $documentService = $container->get(DocumentService::class);

        /** CertificateCreationService $certificateCreationService */
        $certificateCreationService = $container->get(CertificateCreationService::class);

        /** CertificateTypeRepository $certificateTypeRepository */
        $certificateTypeRepository = $entityManager->getRepository(CertificateType::class);

        /** CertificateReplacementRepository $certificateReplacementRepository */
        $certificateReplacementRepository = $entityManager->getRepository(CertificateReplacement::class);

        /** @var LambdaReportService $lambdaReportService */
        $lambdaReportService = $container->get(LambdaReportService::class);

        return new CertificatePrintingController(
            $documentService,
            $container->get('DvsaAuthorisationService'),
            $lambdaReportService,
            $certificateCreationService,
            $motTestService,
            $certificateTypeRepository,
            $certificateReplacementRepository
        );
    }
}


text:
'use strict';

require('configureForRelayOSS');

jest.unmock('RelayRenderer');

const React = require('React');
const ReactTestUtils = require('ReactTestUtils');
const Relay = require('Relay');
const RelayEnvironment = require('RelayEnvironment');
const RelayQueryConfig = require('RelayQueryConfig');
const RelayRenderer = require('RelayRenderer');
const RelayTestUtils = require('RelayTestUtils');

describe('RelayRenderer.validation', () => {
  let MockComponent;
  let MockContainer;
  let ShallowRenderer;

  let queryConfig;
  let environment;
  const {error} = console;

  beforeEach(() => {
    jest.resetModuleRegistry();
    jasmine.addMatchers(RelayTestUtils.matchers);

    MockComponent = React.createClass({render: () => <div />});
    MockContainer = Relay.createContainer(MockComponent, {
      fragments: {},
    });
    ShallowRenderer = ReactTestUtils.createRenderer();

    queryConfig = RelayQueryConfig.genMockInstance();
    environment = new RelayEnvironment();

    console.error = jest.fn(message => {
      throw new Error(message.replace(/Composite propType/, 'propType'));
    });
  });

  afterEach(() => {
    console.error = error;
  });

  it('requires a valid `Container` prop', () => {
    expect(() => ShallowRenderer.render(
      <RelayRenderer queryConfig={queryConfig} environment={environment} />
    )).toThrowError(
      'Warning: Failed propType: Required prop `Container` was not specified ' +
      'in `RelayRenderer`.'
    );

    expect(() => ShallowRenderer.render(
      <RelayRenderer
        Container={MockComponent}
        queryConfig={queryConfig}
        environment={environment}
      />
    )).toThrowError(
      'Warning: Failed propType: Invalid prop `Container` supplied to ' +
      '`RelayRenderer`, expected a RelayContainer.'
    );
  });

  it('requires a valid `queryConfig` prop', () => {
    expect(() => ShallowRenderer.render(
      <RelayRenderer Container={MockContainer} environment={environment} />
    )).toThrowError(
      'Warning: Failed propType: Required prop `queryConfig` was not ' +
      'specified in `RelayRenderer`.'
    );

    expect(() => ShallowRenderer.render(
      <RelayRenderer
        Container={MockContainer}
        queryConfig={{}}
        environment={environment}
      />
    )).toThrowError(
      'Warning: Failed propType: Required prop `queryConfig.name` was not ' +
      'specified in `RelayRenderer`.'
    );
  });

  it('requires a valid `environment` prop', () => {
    expect(() => ShallowRenderer.render(
      <RelayRenderer Container={MockContainer} queryConfig={queryConfig} />
    )).toThrowError(
      'Warning: Failed propType: Invalid prop/context `environment` ' +
      'supplied to `RelayRenderer`, expected `undefined` to be an object ' +
      'conforming to the `RelayEnvironment` interface.'
    );

    expect(() => ShallowRenderer.render(
      <RelayRenderer
        Container={MockContainer}
        queryConfig={queryConfig}
        environment={{}}
      />
    )).toThrowError(
      'Warning: Failed propType: Invalid prop/context `environment` ' +
      'supplied to `RelayRenderer`, expected `[object Object]` to be an ' +
      'object conforming to the `RelayEnvironment` interface.'
    );
  });

});


text:
#ifndef _THREAD_INFO_H
#define _THREAD_INFO_H

#include "HostConnection.h"
#include <pthread.h>
#ifdef HAVE_ANDROID_OS
#include <bionic_tls.h>
#endif

struct EGLContext_t;

struct EGLThreadInfo
{
    EGLThreadInfo() : currentContext(NULL), hostConn(NULL), eglError(EGL_SUCCESS) {}

    EGLContext_t *currentContext;
    HostConnection *hostConn;
    int           eglError;
};

EGLThreadInfo *slow_getEGLThreadInfo();

#ifdef HAVE_ANDROID_OS
    // We have a dedicated TLS slot in bionic
    inline EGLThreadInfo* getEGLThreadInfo() {
        EGLThreadInfo *tInfo =
             (EGLThreadInfo *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]);
        if (!tInfo) {
            tInfo = slow_getEGLThreadInfo();
            ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)tInfo;
        }
        return tInfo;
    }
#else
    inline EGLThreadInfo* getEGLThreadInfo() {
        return slow_getEGLThreadInfo();
    }
#endif

#endif // of _THREAD_INFO_H


text:
<?php defined('BLUDIT') or die('Bludit CMS.');

class Date {

	// Returns string with the date translated
	// Example: $date = 'Mon, 27th March' > 'Lun, 27th Marzo'
	public static function translate($date)
	{
		global $L;

		// If English default language don't translate
		if ($L->currentLanguage()=='en') {
			return $date;
		}

		// Get the array of dates from the language file
		$dates = $L->getDates();
		foreach ($dates as $english=>$anotherLang) {
			$date = preg_replace('/\b'.$english.'\b/u', $anotherLang, $date);
		}
		return $date;
	}

	// Return current Unix timestamp, GMT+0
	public static function unixTime()
	{
		return time();
	}

	// Return the local time/date according to locale settings.
	public static function current($format)
	{
		$Date = new DateTime();
		$output = $Date->format($format);

		return self::translate($output);
	}

	// Returns the current time shifted by offset
	// $offest could be +1 day, +1 month
	public static function currentOffset($format, $offset)
	{
		$Date = new DateTime();
		$Date->modify($offset);
		$output = $Date->format($format);

		return self::translate($output);
	}

	public static function offset($date, $format, $offset)
	{
		$Date = new DateTime($date);
		$Date->modify($offset);
		$output = $Date->format($format);

		return self::translate($output);
	}

	// Format a local time/date according to locale settings.
	public static function format($date, $currentFormat, $outputFormat)
	{
		// Returns a new DateTime instance or FALSE on failure.
		$Date = DateTime::createFromFormat($currentFormat, $date);

		if ($Date!==false) {
			$output = $Date->format($outputFormat);
			return self::translate($output);
		}

		return false;
	}

	public static function convertToUTC($date, $currentFormat, $outputFormat)
	{
		$Date = DateTime::createFromFormat($currentFormat, $date);
		$Date->setTimezone(new DateTimeZone('UTC'));
		$output = $Date->format($outputFormat);

		return self::translate($output);
	}

	public static function timeago($time)
	{
		$time = time() - $time;

		$tokens = array (
			31536000 => 'year',
			2592000 => 'month',
			604800 => 'week',
			86400 => 'day',
			3600 => 'hour',
			60 => 'minute',
			1 => 'second'
		);

		foreach ($tokens as $unit => $text) {
			if ($time < $unit) continue;
			$numberOfUnits = floor($time / $unit);
			return $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
		}
	}

	// DEBUG: Check this function, need to be more fast
	// Return array('Africa/Abidjan'=>'Africa/Abidjan (GMT+0)', ..., 'Pacific/Wallis'=>'Pacific/Wallis (GMT+12)');
	// PHP supported list. http://php.net/manual/en/timezones.php
	public static function timezoneList()
	{
		$tmp = array();

		$timezone_identifiers_list = timezone_identifiers_list();

		foreach($timezone_identifiers_list as $timezone_identifier)
		{
			$date_time_zone = new DateTimeZone($timezone_identifier);
			$date_time = new DateTime('now', $date_time_zone);

			$hours = floor($date_time_zone->getOffset($date_time) / 3600);
			$mins = floor(($date_time_zone->getOffset($date_time) - ($hours*3600)) / 60);

			$hours = 'GMT' . ($hours < 0 ? $hours : '+'.$hours);
			$mins = ($mins > 0 ? $mins : '0'.$mins);

			$text = str_replace("_"," ",$timezone_identifier);

			$tmp[$timezone_identifier] = $text.' ('.$hours.':'.$mins.')';
		}

		return $tmp;
	}
}


text:
SYNONYM

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Parerga lichenol. (Breslau) 222 (1861)

#### Original name
Lecidea glaucophaea Körb.

### Remarks
null


text:
module Generics.GPAH.Derive.PPrint where

import Generics.GPAH.Derive.Base
import Text.CSV
import System.IO
import qualified Data.Map as M
import Data.Function
import Data.List

pprint :: Analysis -> FilePath -> IO ()
pprint (Analysis a1 a2 a3 a4) fp = do
  let p = [["DeriveTemplateHaskellDirectives", show $ sortBy (flip compare `on` snd) $ M.toList a1]
          ,["DerivePreprocessingDirectives",  show $ sortBy (flip compare `on` snd) $ M.toList a2]
          ,["DrIFTNormalDirectives",  show $ sortBy (flip compare `on` snd) $ M.toList a3]
          ,["DrIFTGlobalDirectives",  show $ sortBy (flip compare `on` snd) $ M.toList a4]
          ]
      pCSV = printCSV p

  writeFile fp pCSV

  putStrLn "Derive+DrIFT Results:\n###############"
  putStrLn pCSV


text:
MathJax.Hub.Config({
  config: ["MMLorHTML.js"],
  extensions: ["asciimath2jax.js","MathEvents.js","MathZoom.js","MathMenu.js","toMathML.js","fast-preview.js","AssistiveMML.js","[Contrib]/a11y/accessibility-menu.js"],
  jax: ["input/AsciiMath","output/HTML-CSS","output/NativeMML","output/PreviewHTML"]
});

MathJax.Ajax.loadComplete("[MathJax]/config/AM_HTMLorMML-full.js");


text:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:stretchColumns="1">
	<TableRow>
		<TextView
	        android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="路径:" />
		<EditText
			android:id="@+id/selectedFile"
			android:singleLine="true"
	        android:layout_width="10px"
			android:layout_height="wrap_content"
			android:hint="Please select a file..." />
	    <ImageButton
	        android:id="@+id/selectFileBtn"
	        android:background="@drawable/folder3"
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content" />
	</TableRow>
	<TableRow>
		<Button
	        android:id="@+id/uploadBtn"
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content"
	        android:layout_span="3"
	        android:background="@drawable/button"
	        android:text="上传文件" />
    </TableRow>
    <TableRow>
		<TextView
	         android:id="@+id/fileName"
		     android:layout_width="match_parent"
		     android:layout_height="wrap_content"
	         android:layout_span="3"
		     android:text="" />
    </TableRow>
    <TableRow>
		<ProgressBar
		    style="?android:attr/progressBarStyleHorizontal"
	        android:id="@+id/progressBar"
	        android:visibility="gone"
	        android:layout_width="match_parent"
	        android:layout_height="30px"
	        android:max="100"
	        android:progress="0"
	        android:layout_span="3"
	        android:text="文件正在上传......" />
    </TableRow>
    <TableRow>
		<TextView
	         android:id="@+id/uploadedPercent"
		     android:layout_width="match_parent"
		     android:layout_height="wrap_content"
	         android:layout_span="2"
		     android:text="" />
		<TextView
	         android:id="@+id/uploadedSpeed"
		     android:layout_width="match_parent"
		     android:layout_height="wrap_content"
		     android:gravity="center"
		     android:text="" />
    </TableRow>
</TableLayout>


text:
<?php

class ITSEC_File_Change_Admin {

	private
		$settings,
		$core,
		$module_path;

	function run( $core ) {

		$this->core        = $core;
		$this->settings    = get_site_option( 'itsec_file_change' );
		$this->module_path = ITSEC_Lib::get_module_path( __FILE__ );

		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); //enqueue scripts for admin page
		add_action( 'itsec_add_admin_meta_boxes', array( $this, 'itsec_add_admin_meta_boxes' ) ); //add meta boxes to admin page
		add_action( 'itsec_admin_init', array( $this, 'itsec_admin_init' ) ); //initialize admin area
		add_action( 'wp_ajax_itsec_file_change_ajax', array( $this, 'wp_ajax_itsec_file_change_ajax' ) );
		add_action( 'wp_ajax_itsec_file_change_warning_ajax', array( $this, 'wp_ajax_itsec_file_change_warning_ajax' ) );
		add_action( 'wp_ajax_itsec_jquery_filetree_ajax', array( $this, 'wp_ajax_itsec_jquery_filetree_ajax' ) );

		add_filter( 'itsec_add_dashboard_status', array( $this, 'itsec_add_dashboard_status' ) ); //add information for plugin status
		add_filter( 'itsec_logger_displays', array( $this, 'itsec_logger_displays' ) ); //adds logs metaboxes
		add_filter( 'itsec_tracking_vars', array( $this, 'itsec_tracking_vars' ) );

		//manually save options on multisite
		if ( is_multisite() ) {
			add_action( 'itsec_admin_init', array( $this, 'itsec_admin_init_multisite' ) ); //save multisite options
		}

	}

	/**
	 * Add Files Admin Javascript
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function admin_enqueue_scripts() {

		global $itsec_globals;

		wp_enqueue_script( 'itsec_file_change_warning_js', $this->module_path . 'js/admin-file-change-warning.js', array( 'jquery' ), $itsec_globals['plugin_build'] );
		wp_localize_script(
			'itsec_file_change_warning_js',
			'itsec_file_change_warning',
			array(
				'nonce' => wp_create_nonce( 'itsec_file_change_warning' ),
				'url'   => admin_url() . 'admin.php?page=toplevel_page_itsec_logs&itsec_log_filter=file_change',
			)
		);

		if ( isset( get_current_screen()->id ) && ( strpos( get_current_screen()->id, 'security_page_toplevel_page_itsec_settings' ) !== false || strpos( get_current_screen()->id, 'security_page_toplevel_page_itsec_logs' ) !== false || strpos( get_current_screen()->id, 'dashboard' ) !== false ) ) {

			wp_enqueue_script( 'itsec_file_change_js', $this->module_path . 'js/admin-file-change.js', array( 'jquery' ), $itsec_globals['plugin_build'] );
			wp_localize_script(
				'itsec_file_change_js',
				'itsec_file_change',
				array(
					'mem_limit'            => ITSEC_Lib::get_memory_limit(),
					'text'                 => __( 'Warning: Your server has less than 128MB of RAM dedicated to PHP. If you have many files in your installation or a lot of active plugins activating this feature may result in your site becoming disabled with a memory error. See the plugin homepage for more information.', 'it-l10n-better-wp-security' ),
					'module_path'          => $this->module_path,
					'button_text'          => isset( $this->settings['split'] ) && $this->settings['split'] === true ? __( 'Scan Next File Chunk', 'it-l10n-better-wp-security' ) : __( 'Scan Files Now', 'it-l10n-better-wp-security' ),
					'scanning_button_text' => __( 'Scanning...', 'it-l10n-better-wp-security' ),
					'no_changes'           => __( 'No changes were detected.', 'it-l10n-better-wp-security' ),
					'changes'              => __( 'Changes were detected. Please check the log page for details.', 'it-l10n-better-wp-security' ),
					'error'                => __( 'An error occured. Please try again later', 'it-l10n-better-wp-security' ),
					'ABSPATH'              => ITSEC_Lib::get_home_path(),
					'nonce'                => wp_create_nonce( 'itsec_do_file_check' ),
				)
			);

			wp_enqueue_script( 'itsec_jquery_filetree', $this->module_path . 'filetree/jqueryFileTree.js', array( 'jquery' ), '1.01' );
			wp_localize_script(
				'itsec_jquery_filetree',
				'itsec_jquery_filetree',
				array(
					'nonce' => wp_create_nonce( 'itsec_jquery_filetree' ),
				)
			);

			wp_register_style( 'itsec_jquery_filetree_style', $this->module_path . 'filetree/jqueryFileTree.css', array(), $itsec_globals['plugin_build'] ); //add multi-select css
			wp_enqueue_style( 'itsec_jquery_filetree_style' );

			wp_register_style( 'itsec_file_change_css', $this->module_path . 'css/admin-file-change.css', array(), $itsec_globals['plugin_build'] ); //add multi-select css
			wp_enqueue_style( 'itsec_file_change_css' );

		}

	}

	/**
	 * Display admin warning
	 *
	 * @since 4.0
	 *
	 * Displays a warning to adminstrators when file changes have been detected
	 *
	 **/
	public function dashboard_warning() {

		global $blog_id; //get the current blog id

		if ( ( is_multisite() && ( $blog_id != 1 || ! current_user_can( 'manage_network_options' ) ) ) || ! current_user_can( 'activate_plugins' ) ) { //only display to network admin if in multisite
			return;
		}

		//if there is a warning to display
		if ( get_site_option( 'itsec_file_change_warning' ) == '1' ) {

			if ( ! function_exists( 'itsec_intrusion_warning' ) ) {

				function itsec_intrusion_warning() {

					global $itsec_globals;

					printf(
						'

%s %s

<input type="button" id="itsec_go_to_logs" class="button-primary" value="%s"> <input type="button" id="itsec_dismiss_file_change_warning" class="button-secondary" value="%s">

',
						$itsec_globals['plugin_name'],
						__( 'has noticed a change to some files in your WordPress site. Please review the logs to make sure your system has not been compromised.', 'it-l10n-better-wp-security' ),
						__( 'View Logs', 'it-l10n-better-wp-security' ),
						__( 'Dismiss Warning', 'it-l10n-better-wp-security' )

					);

				}

			}

			//put the warning in the right spot
			if ( is_multisite() ) {
				add_action( 'network_admin_notices', 'itsec_intrusion_warning' ); //register notification
			} else {
				add_action( 'admin_notices', 'itsec_intrusion_warning' ); //register notification
			}

		}

		//if they've clicked a button hide the notice
		if ( ( isset( $_GET['bit51_view_logs'] ) || isset( $_GET['bit51_dismiss_warning'] ) ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'bit51-nag' ) ) {

			//Get the options
			if ( is_multisite() ) {

				switch_to_blog( 1 );

				delete_option( 'bwps_intrusion_warning' );

				restore_current_blog();

			} else {

				delete_option( 'bwps_intrusion_warning' );

			}

			//take them back to where they started
			if ( isset( $_GET['bit51_dismiss_warning'] ) ) {
				wp_redirect( $_SERVER['HTTP_REFERER'], 302 );
			}

			//take them to the correct logs page
			if ( isset( $_GET['bit51_view_logs'] ) ) {
				if ( is_multisite() ) {
					wp_redirect( admin_url() . 'network/admin.php?page=better-wp-security-logs#file-change', 302 );
				} else {
					wp_redirect( admin_url() . 'admin.php?page=better-wp-security-logs#file-change', 302 );
				}
			}

		}

	}

	/**
	 * Echos the one-time file change scan form
	 *
	 * @since 4.0
	 *
	 * @param string $origin the origin
	 *
	 * @return void
	 */
	public function file_change_form( $origin ) {

		if ( isset( $this->settings['enabled'] ) && $this->settings['enabled'] === true ) {

			echo '<form id="itsec_one_time_file_check" method="post" action="">';
			echo wp_nonce_field( 'itsec_do_file_check', 'wp_nonce' );
			echo '<input type="hidden" name="itsec_file_change_origin" value="' . sanitize_text_field( $origin ) . '">';
			echo '
' . __( "Press the button below to scan your site's files for changes. Note that if changes are found this will take you to the logs page for details.", 'it-l10n-better-wp-security' ) . '
';
			echo '
<input type="submit" id="itsec_one_time_file_check_submit" class="button-primary" value="' . ( isset( $this->settings['split'] ) && $this->settings['split'] === true ? __( 'Scan Next File Chunk', 'it-l10n-better-wp-security' ) : __( 'Scan Files Now', 'it-l10n-better-wp-security' ) ) . '" />
';
			echo '

';
			echo '</form>';

		}

	}

	/**
	 * Add meta boxes to primary options pages
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function itsec_add_admin_meta_boxes() {

		$id    = 'file_change_options';
		$title = __( 'File Change Detection', 'it-l10n-better-wp-security' );

		add_meta_box(
			$id,
			$title,
			array( $this, 'metabox_advanced_file_change_settings' ),
			'security_page_toplevel_page_itsec_settings',
			'advanced',
			'core'
		);

		$this->core->add_toc_item(
			array(
				'id'    => $id,
				'title' => $title,
			)
		);

	}

	/**
	 * Sets the status in the plugin dashboard
	 *
	 * @since 4.0
	 *
	 * @return array statuses
	 */
	public function itsec_add_dashboard_status( $statuses ) {

		if ( $this->settings['enabled'] === true ) {

			$status_array = 'safe-medium';
			$status       = array(
				'text' => __( 'Your site will detect changes to your files.', 'it-l10n-better-wp-security' ),
				'link' => '#itsec_file_change_enabled',
			);

		} else {

			$status_array = 'medium';
			$status       = array(
				'text' => __( 'Your website is not looking for changed files. Consider turning on file change detections.', 'it-l10n-better-wp-security' ),
				'link' => '#itsec_file_change_enabled',
			);

		}

		array_push( $statuses[ $status_array ], $status );

		return $statuses;

	}

	/**
	 * Execute admin initializations
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function itsec_admin_init() {

		$this->dashboard_warning();

		//Add Settings sections
		add_settings_section(
			'file_change-enabled',
			__( 'File Change Detection', 'it-l10n-better-wp-security' ),
			'__return_empty_string',
			'security_page_toplevel_page_itsec_settings'
		);

		add_settings_section(
			'file_change-settings',
			__( 'File Change Detection Settings', 'it-l10n-better-wp-security' ),
			'__return_empty_string',
			'security_page_toplevel_page_itsec_settings'
		);

		//File Change Detection Fields
		add_settings_field(
			'itsec_file_change[enabled]',
			__( 'File Change Detection', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_enabled' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-enabled'
		);

		add_settings_field(
			'itsec_file_change[split]',
			__( 'Split File Scanning', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_split' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		add_settings_field(
			'itsec_file_change[method]',
			__( 'Include/Exclude Files and Folders', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_method' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		add_settings_field(
			'itsec_file_change[file_list]',
			__( 'Files and Folders List', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_file_list' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		add_settings_field(
			'itsec_file_change[types]',
			__( 'Ignore File Types', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_types' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		add_settings_field(
			'itsec_file_change[email]',
			__( 'Email File Change Notifications', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_email' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		add_settings_field(
			'itsec_file_change[notify_admin]',
			__( 'Display File Change Admin Warning', 'it-l10n-better-wp-security' ),
			array( $this, 'settings_field_notify_admin' ),
			'security_page_toplevel_page_itsec_settings',
			'file_change-settings'
		);

		//Register the settings field for the entire module
		register_setting(
			'security_page_toplevel_page_itsec_settings',
			'itsec_file_change',
			array( $this, 'sanitize_module_input' )
		);

	}

	/**
	 * Prepare and save options in network settings
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function itsec_admin_init_multisite() {

		if ( isset( $_POST['itsec_file_change'] ) ) {

			if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'security_page_toplevel_page_itsec_settings-options' ) ) {
				die( __( 'Security error!', 'it-l10n-better-wp-security' ) );
			}

			update_site_option( 'itsec_file_change', $_POST['itsec_file_change'] ); //we must manually save network options

		}

	}

	/**
	 * Array of displays for the logs screen
	 *
	 * @since 4.0
	 *
	 * @param array $displays metabox array
	 *
	 * @return array metabox array
	 */
	public function itsec_logger_displays( $displays ) {

		if ( isset( $this->settings['enabled'] ) && $this->settings['enabled'] === true ) {

			$displays[] = array(
				'module'   => 'file_change',
				'title'    => __( 'File Change History', 'it-l10n-better-wp-security' ),
				'callback' => array( $this, 'logs_metabox_content' )
			);

		}

		return $displays;

	}

	/**
	 * Adds fields that will be tracked for Google Analytics
	 *
	 * @since 4.0
	 *
	 * @param array $vars tracking vars
	 *
	 * @return array tracking vars
	 */
	public function itsec_tracking_vars( $vars ) {

		$vars['itsec_file_change'] = array(
			'enabled' => '0:b',
			'method'  => '1:b',
			'email'   => '1:b',
		);

		return $vars;

	}

	/**
	 * Render the file change log metabox
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function logs_metabox_content() {

		global $itsec_globals;

		$this->file_change_form( 'settings' );

		if ( ! class_exists( 'ITSEC_File_Change_Log' ) ) {
			require( dirname( __FILE__ ) . '/class-itsec-file-change-log.php' );
		}

		if ( isset( $this->settings['enabled'] ) && $this->settings['enabled'] === true ) {

			// If we're splitting the file check run it every 6 hours. Else daily.
			if ( isset( $this->settings['split'] ) && $this->settings['split'] === true ) {
				$interval = 12342;
			} else {
				$interval = 86400;
			}

			$next_run_raw = $this->settings['last_run'] + $interval;

			if ( date( 'j', $next_run_raw ) == date( 'j', $itsec_globals['current_time'] ) ) {
				$next_run_day = __( 'Today', 'it-l10n-better-wp-security' );
			} else {
				$next_run_day = __( 'Tomorrow', 'it-l10n-better-wp-security' );
			}

			$next_run = $next_run_day . ' at ' . date( 'g:i a', $next_run_raw );

			echo '
' . __( 'Next automatic scan at: ', 'it-l10n-better-wp-security' ) . '' . $next_run . '*
';
			echo '
*' . __( 'Automatic file change scanning is triggered by a user visiting your page and may not happen exactly at the time listed.', 'it-l10n-better-wp-security' ) . '';

		}

		$log_display = new ITSEC_File_Change_Log();

		$log_display->prepare_items();
		$log_display->display();

	}

	/**
	 * Render the settings metabox
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function metabox_advanced_file_change_settings() {

		echo '
' . __( 'Even the best security solutions can fail. How do you know if someone gets into your site? You will know because they will change something. File Change detection will tell you what files have changed in your WordPress installation alerting you to changes not made by yourself. Unlike other solutions this plugin will look only at your installation and compare files to the last check instead of comparing them with a remote installation thereby taking into account whether or not you modify the files yourself.', 'it-l10n-better-wp-security' ) . '
';

		echo $this->file_change_form( 'logs' );

		$this->core->do_settings_section( 'security_page_toplevel_page_itsec_settings', 'file_change-enabled', false );
		$this->core->do_settings_section( 'security_page_toplevel_page_itsec_settings', 'file_change-settings', false );

		echo '
' . PHP_EOL;

		settings_fields( 'security_page_toplevel_page_itsec_settings' );

		echo '<input class="button-primary" name="submit" type="submit" value="' . __( 'Save All Changes', 'it-l10n-better-wp-security' ) . '" />' . PHP_EOL;

		echo '
' . PHP_EOL;

	}

	/**
	 * Sanitize and validate input
	 *
	 * @since 4.0
	 *
	 * @param  Array $input array of input fields
	 *
	 * @return Array         Sanitized array
	 */
	public function sanitize_module_input( $input ) {

		global $itsec_globals;

		//File Change Detection Fields
		$input['enabled']      = ( isset( $input['enabled'] ) && intval( $input['enabled'] == 1 ) ? true : false );
		$input['split']        = ( isset( $input['split'] ) && intval( $input['split'] == 1 ) ? true : false );
		$input['method']       = ( isset( $input['method'] ) && intval( $input['method'] == 1 ) ? true : false );
		$input['email']        = ( isset( $input['email'] ) && intval( $input['email'] == 1 ) ? true : false );
		$input['notify_admin'] = ( isset( $input['notify_admin'] ) && intval( $input['notify_admin'] == 1 ) ? true : false );
		$input['last_chunk']   = ( isset( $input['last_chunk'] ) ? $input['last_chunk'] : false );

		if ( ! is_array( $input['file_list'] ) ) {
			$file_list = explode( PHP_EOL, $input['file_list'] );
		} else {
			$file_list = $input['file_list'];
		}

		$good_files = array();

		foreach ( $file_list as $file ) {
			$good_files[] = sanitize_text_field( trim( $file ) );
		}

		$input['file_list'] = $good_files;

		if ( ! is_array( $input['types'] ) ) {
			$file_types = explode( PHP_EOL, $input['types'] );
		} else {
			$file_types = $input['types'];
		}

		$good_types = array();

		foreach ( $file_types as $file_type ) {

			$file_type = trim( $file_type );

			if ( strlen( $file_type ) > 0 && $file_type != '.' ) {

				$good_type = sanitize_text_field( '.' . str_replace( '.', '', $file_type ) );

				$good_types[] = sanitize_text_field( trim( $good_type ) );

			}
		}

		$input['types'] = $good_types;

		if ( $input['split'] === true ) {
			$interval = 12282;
		} else {
			$interval = 86340;
		}

		if ( defined( 'ITSEC_DOING_FILE_CHECK' ) && ITSEC_DOING_FILE_CHECK === true ) {
			$input['last_run'] = $itsec_globals['current_time'];
		} else {
			$input['last_run'] = isset( $this->settings['last_run'] ) && $this->settings['last_run'] > $itsec_globals['current_time'] - $interval ? $this->settings['last_run'] : ( $itsec_globals['current_time'] - $interval + 120 );
		}

		if ( is_multisite() ) {

			$this->core->show_network_admin_notice( false );

			$this->settings = $input;

		}

		return $input;

	}

	/**
	 * echos Email File Change Notifications Field
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function settings_field_email() {

		if ( isset( $this->settings['email'] ) && $this->settings['email'] === false ) {
			$email = 0;
		} else {
			$email = 1;
		}

		echo '<input type="checkbox" id="itsec_file_change_email" name="itsec_file_change[email]" value="1" ' . checked( 1, $email, false ) . '/>';
		echo ' ' . __( 'Email file change notifications', 'it-l10n-better-wp-security' ) . '';
		echo '
' . __( 'Notifications will be sent to all emails set to receive notifications on the global settings page.', 'it-l10n-better-wp-security' ) . '
';

	}

	/**
	 * echos Enable File Change Detection Field
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function settings_field_enabled() {

		if ( isset( $this->settings['enabled'] ) && $this->settings['enabled'] === true ) {
			$enabled = 1;
		} else {
			$enabled = 0;
		}

		echo '<input type="checkbox" id="itsec_file_change_enabled" name="itsec_file_change[enabled]" value="1" ' . checked( 1, $enabled, false ) . '/>';
		echo ' ' . __( 'Enable File Change detection', 'it-l10n-better-wp-security' ) . '';

	}

	/**
	 * echos Enable File Change List Field
	 *
	 * @param  array $args field arguments
	 *
	 * @return void
	 */
	public function settings_field_file_list() {

		if ( isset( $this->settings['file_list'] ) && is_array( $this->settings['file_list'] ) ) {
			$file_list = implode( PHP_EOL, $this->settings['file_list'] );
		} else {
			$file_list = '';
		}

		echo '
' . __( 'Exclude files or folders by clicking the red minus next to the file or folder name.', 'it-l10n-better-wp-security' ) . '
';
		echo '
';
		echo '

';
		echo '
';
		echo '<textarea id="itsec_file_change_file_list" name="itsec_file_change[file_list]" wrap="off">' . $file_list . PHP_EOL . '</textarea>';
		echo '

';

	}

	/**
	 * echos method Field
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function settings_field_method() {

		if ( isset( $this->settings['method'] ) ) {
			$method = $this->settings['method'] === true ? 1 : 0;
		} else {
			$method = 1;
		}

		echo '<select id="itsec_file_change_method" name="itsec_file_change[method]">';

		echo '<option value="1" ' . selected( $method, '1' ) . '>' . __( 'Exclude Selected', 'it-l10n-better-wp-security' ) . '</option>';
		echo '<option value="0" ' . selected( $method, '0' ) . '>' . __( 'Include Selected', 'it-l10n-better-wp-security' ) . '</option>';
		echo '</select>
';
		echo ' ' . __( 'Include/Exclude Files', 'it-l10n-better-wp-security' ) . '';
		echo '
' . __( 'Select whether we should exclude files and folders selected or whether the scan should only include files and folders selected.' ) . '
';

	}

	/**
	 * echos Email File Change Notifications Field
	 *
	 * @param  array $args field arguments
	 *
	 * @return void
	 */
	public function settings_field_notify_admin() {

		if ( isset( $this->settings['notify_admin'] ) && $this->settings['notify_admin'] === false ) {
			$notify_admin = 0;
		} else {
			$notify_admin = 1;
		}

		echo '<input type="checkbox" id="itsec_file_change_notify_admin" name="itsec_file_change[notify_admin]" value="1" ' . checked( 1, $notify_admin, false ) . '/>';
		echo ' ' . __( 'Display file change admin warning', 'it-l10n-better-wp-security' ) . '';
		echo '
' . __( 'Disabling this feature will prevent the file change warning from displaying to the site administrator in the WordPress Dashboard. Note that disabling both the error message and the email notification will result in no notifications of file changes. The only way you will be able to tell is by manually checking the log files.', 'it-l10n-better-wp-security' ) . '
';

	}

	/**
	 * echos split file checks Field
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function settings_field_split() {

		if ( isset( $this->settings['split'] ) && $this->settings['split'] === true ) {
			$split = 1;
		} else {
			$split = 0;
		}

		echo '<input type="checkbox" id="itsec_file_change_split" name="itsec_file_change[split]" value="1" ' . checked( 1, $split, false ) . '/>';
		echo ' ' . __( 'Split file checking into chunks.', 'it-l10n-better-wp-security' ) . '';
		echo '
 ' . __( 'Splits file checking into 7 chunks (plugins, themes, wp-admin, wp-includes, uploads, the rest of wp-content and everything that is left over) and divides the checks evenly over the course of a day. This feature may result in more notifications but will allow for the scanning of bigger sites to continue even on a lower-end web host.', 'it-l10n-better-wp-security' ) . '
';

	}

	/**
	 * echos file change types Field
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function settings_field_types() {

		if ( isset( $this->settings['types'] ) && is_array( $this->settings['types'] ) ) {
			$types = implode( PHP_EOL, $this->settings['types'] );
		} else {
			$types = implode( PHP_EOL, array(
				'.jpg',
				'.jpeg',
				'.png',
				'.log',
				'.mo',
				'.po',
			) );
		}

		echo '<textarea id="itsec_file_change_types" name="itsec_file_change[types]" wrap="off" cols="20" rows="10">' . $types . PHP_EOL . '</textarea>
';
		echo ' ' . __( 'File types listed here will not be checked for changes. While it is possible to change files such as images it is quite rare and nearly all known WordPress attacks exploit php, js and other text files.', 'it-l10n-better-wp-security' ) . '';

	}

	/**
	 * Executes one-time backup.
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function wp_ajax_itsec_file_change_warning_ajax() {

		if ( ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'itsec_file_change_warning' ) ) {
			die( __( 'Security error!', 'it-l10n-better-wp-security' ) );
		}

		die( delete_site_option( 'itsec_file_change_warning' ) );

	}

	/**
	 * Executes one-time backup.
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function wp_ajax_itsec_jquery_filetree_ajax() {

		global $itsec_globals;

		if ( ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'itsec_jquery_filetree' ) || ! current_user_can( $itsec_globals['plugin_access_lvl'] ) ) {
			die( __( 'Security error!', 'it-l10n-better-wp-security' ) );
		}

		$directory = sanitize_text_field( $_POST['dir'] );

		$directory = urldecode( $directory );

		if ( file_exists( $directory ) ) {

			$files = scandir( $directory );

			natcasesort( $files );

			if ( count( $files ) > 2 ) { /* The 2 accounts for . and .. */

				echo "
";

				//two loops keep directories sorted before files

				// All files and directories (alphabetical sorting)
				foreach ( $files as $file ) {

					if ( $file != '.' && $file != '..' && file_exists( $directory . $file ) && is_dir( $directory . $file ) ) {

						echo '
' . htmlentities( $file ) . '

';

					} elseif ( $file != '.' && $file != '..' && file_exists( $directory . $file ) && ! is_dir( $directory . $file ) ) {

						$ext = preg_replace( '/^.*\./', '', $file );
						echo '
' . htmlentities( $file ) . '

';

					}

				}

				echo "
";

			}

		}

		exit;

	}

	/**
	 * Executes one-time backup.
	 *
	 * @since 4.0
	 *
	 * @return void
	 */
	public function wp_ajax_itsec_file_change_ajax() {

		if ( ! wp_verify_nonce( sanitize_text_field( $_POST['nonce'] ), 'itsec_do_file_check' ) ) {
			die( __( 'Security error!', 'it-l10n-better-wp-security' ) );
		}

		$module = new ITSEC_File_Change();
		$module->run();

		die( $module->execute_file_check( false ) );

	}

}


text:
package alluxio.table.common.udb;

/**
 * The under database factory interface.
 */
public interface UnderDatabaseFactory {

  /**
   * @return the type of under database for the factory
   */
  String getType();

  /**
   * Creates a new instance of the udb. Creation must not interact with external services.
   *
   * @param udbContext the db context
   * @param configuration configuration values
   * @return a new instance of the under database
   */
  UnderDatabase create(UdbContext udbContext, UdbConfiguration configuration);
}