text:
package org.apache.flink.runtime.io.network.partition;

import org.apache.flink.runtime.clusterframework.types.ResourceID;
import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;

import java.util.Optional;

/**
 * Factory for {@link PartitionTracker}.
 */
@FunctionalInterface
public interface PartitionTrackerFactory {

	/**
	 * Creates a new PartitionTracker.
	 *
	 * @param taskExecutorGatewayLookup lookup function to access task executor gateways
	 * @return created PartitionTracker
	 */
	PartitionTracker create(TaskExecutorGatewayLookup taskExecutorGatewayLookup);

	/**
	 * Lookup function for {@link TaskExecutorGateway}.
	 */
	@FunctionalInterface
	interface TaskExecutorGatewayLookup {

		/**
		 * Returns a {@link TaskExecutorGateway} corresponding to the given ResourceID.
		 *
		 * @param taskExecutorId id of the task executor to look up.
		 * @return optional task executor gateway
		 */
		Optional<TaskExecutorGateway> lookup(ResourceID taskExecutorId);
	}
}


text:
export interface Position {
    x?: number | undefined;
    y?: number | undefined;
}

export interface ScrollingState {
    isMoving: boolean;
    isDragging: boolean;
    position: Required<Position>;
    dragOffset: number;
    borderCollision: {
        left: boolean;
        right: boolean;
        top: boolean;
        bottom: boolean;
    };
}

export interface ScrollBoosterOptions {
    content?: HTMLElement | null | undefined;
    viewport: HTMLElement | null;
    scrollMode?: 'transform' | 'native' | undefined;
    direction?: 'horizontal' | 'vertical' | 'all' | undefined;
    bounce?: boolean | undefined;
    textSelection?: boolean | undefined;
    inputsFocus?: boolean | undefined;
    pointerMode?: 'touch' | 'mouse' | 'all' | undefined;
    friction?: number | undefined;
    bounceForce?: number | undefined;
    emulateScroll?: boolean | undefined;
    onUpdate?: ((state: ScrollingState) => void) | undefined;
    onClick?: ((state: ScrollingState, event: Event) => void) | undefined;
    shouldScroll?: ((state: ScrollingState, event: Event) => boolean) | undefined;
}

export default class ScrollBooster {
    constructor(options: ScrollBoosterOptions);

    setPosition(position: Position): void;

    scrollTo(position: Position): void;

    updateMetrics(): void;

    updateOptions(options: Partial<ScrollBoosterOptions>): void;

    getState(): ScrollingState;

    destroy(): void;
}

redpajama_set_name: RedPajamaGithub


text:
require "spec_helper.rb"

describe Responsys::Api::List do

  before(:context) do
    @list = Responsys::Api::Object::InteractObject.new(DATA[:folder], DATA[:lists][:list1][:name])
    @query_column_email = Responsys::Api::Object::QueryColumn.new("EMAIL_ADDRESS")
    @multiple_users_email = [DATA[:users][:user1][:EMAIL_ADDRESS], DATA[:users][:user2][:EMAIL_ADDRESS], DATA[:users][:user3][:EMAIL_ADDRESS]]
    @user1_email = DATA[:users][:user1][:EMAIL_ADDRESS]
    @user1_mobile = DATA[:users][:user1][:MOBILE_NUMBER]
    @user3_mobile = DATA[:users][:user3][:MOBILE_NUMBER]
  end

  context "Retrieve info from list with multiple users" do

    it "should get a ok status" do
      VCR.use_cassette("api/list/retrieve") do
        response = Responsys::Api::Client.new.retrieve_list_members(@list, @query_column_email, %w(EMAIL_ADDRESS_ MOBILE_NUMBER_), @multiple_users_email)

        expect(response[:status]).to eq("ok")
      end
    end

    it "should get a value from the data" do
      VCR.use_cassette("api/list/retrieve") do
        response = Responsys::Api::Client.new.retrieve_list_members(@list, @query_column_email, %w(EMAIL_ADDRESS_ MOBILE_NUMBER_), @multiple_users_email)

        expect(response[:data][0][:MOBILE_NUMBER_]).to eq(@user1_mobile)
      end
    end

    it "should get a nil value" do
      VCR.use_cassette("api/list/retrieve") do
        response = Responsys::Api::Client.new.retrieve_list_members(@list, @query_column_email, %w(EMAIL_ADDRESS_ MOBILE_NUMBER_), @multiple_users_email)

        expect(response[:data][1][:MOBILE_NUMBER_]).to be(nil)
      end
    end

    it "should return a single result" do
      VCR.use_cassette("api/list/retrieve_single") do
        response = Responsys::Api::Client.new.retrieve_list_members(@list, @query_column_email, %w(EMAIL_ADDRESS_ MOBILE_NUMBER_), [@user1_email])

        expect(response[:data][0][:EMAIL_ADDRESS_]).to eq(@user1_email)
      end
    end

    it "should return a single field in a single record" do
      VCR.use_cassette("api/list/retrieve_single_single") do
        response = Responsys::Api::Client.new.retrieve_list_members(@list, @query_column_email, %w(EMAIL_ADDRESS_), [@user1_email])

        expect(response[:data][0][:EMAIL_ADDRESS_]).to eq(@user1_email)
      end
    end
  end

  context "Merge list members" do
    it "should reject no record" do
      VCR.use_cassette("api/list/merge") do
        data = [{ Email_Address_: @user1_email, Mobile_Number_: @user1_mobile }]
        response = Responsys::Api::Client.new.merge_list_members(@list, Responsys::Api::Object::RecordData.new(data), merge_rule = Responsys::Api::Object::ListMergeRule.new(matchColumnName1: "Mobile_Number_"))

        expect(response[:data][0][:result][:rejected_count].to_i).to eq(0)
      end
    end
  end
end


text:
require('es6-promise').polyfill();

function withXHR() {

  this.request = function(options) {
    var url = options.url;
    var method = options.method || 'GET';
    var data = options.data ? JSON.stringify(options.data) : undefined;

    function request(resolve, reject) {
      var xhr = new XMLHttpRequest();
      xhr.responseType = 'json';

      xhr.addEventListener('readystatechange', readystatechangeHandler.bind(this), false);
      xhr.upload.addEventListener('progress', progressHandler.bind(this), false);

      xhr.open(method, url, true);
      xhr.send(data);

      function readystatechangeHandler(response) {
        if (xhr.readyState == 4 && xhr.status == 200) {
          // triggerEvent.call(this, 'done');
          resolve(xhr.response);
        }
        else if (xhr.readyState == 4 && xhr.status != 200) {
          // triggerEvent.call(this, 'fail');
          reject(xhr.response);
        }
      };

      function progressHandler(response) {
        triggerEvent.call(this, 'progress');
      };

      function triggerEvent(e) {
        var event = options.events[e];
        if (event) {
          this.trigger(event, xhr.response);
        }
      };

    }

    return new Promise(request.bind(this))
      .catch(function(err) {
        console.log(err);
      });

  };

}

module.exports = withXHR;


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.resourcemanager.compute.models;

import com.azure.core.util.ExpandableStringEnum;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Collection;

/**
 * Specifies the mode of VM Guest Patch Assessment for the IaaS virtual machine.

 Possible values
 * are:

 **ImageDefault** - You control the timing of patch assessments on a virtual machine.
 *

 **AutomaticByPlatform** - The platform will trigger periodic patch assessments. The property
 * provisionVMAgent must be true.
 */
public final class LinuxPatchAssessmentMode extends ExpandableStringEnum<LinuxPatchAssessmentMode> {
    /** Static value ImageDefault for LinuxPatchAssessmentMode. */
    public static final LinuxPatchAssessmentMode IMAGE_DEFAULT = fromString("ImageDefault");

    /** Static value AutomaticByPlatform for LinuxPatchAssessmentMode. */
    public static final LinuxPatchAssessmentMode AUTOMATIC_BY_PLATFORM = fromString("AutomaticByPlatform");

    /**
     * Creates or finds a LinuxPatchAssessmentMode from its string representation.
     *
     * @param name a name to look for.
     * @return the corresponding LinuxPatchAssessmentMode.
     */
    @JsonCreator
    public static LinuxPatchAssessmentMode fromString(String name) {
        return fromString(name, LinuxPatchAssessmentMode.class);
    }

    /**
     * Gets known LinuxPatchAssessmentMode values.
     *
     * @return known LinuxPatchAssessmentMode values.
     */
    public static Collection<LinuxPatchAssessmentMode> values() {
        return values(LinuxPatchAssessmentMode.class);
    }
}


text:
<?php

namespace MiladRahimi\PhpRouter\Tests\Features;

use Laminas\Diactoros\ServerRequest;
use MiladRahimi\PhpRouter\Tests\Common\SampleController;
use MiladRahimi\PhpRouter\Tests\TestCase;
use Throwable;

class HttpMethodTest extends TestCase
{
    /**
     * @throws Throwable
     */
    public function test_a_get_route()
    {
        $this->mockRequest('GET', 'http://example.com/');

        $router = $this->router();
        $router->get('/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_a_post_route()
    {
        $this->mockRequest('POST', 'http://example.com/');

        $router = $this->router();
        $router->post('/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_a_put_route()
    {
        $this->mockRequest('PUT', 'http://example.com/');

        $router = $this->router();
        $router->put('/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_a_patch_route()
    {
        $this->mockRequest('PATCH', 'http://example.com/');

        $router = $this->router();
        $router->patch('/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_a_delete_route()
    {
        $this->mockRequest('DELETE', 'http://example.com/');

        $router = $this->router();
        $router->delete('/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_map_a_post_route()
    {
        $this->mockRequest('POST', 'http://example.com/');

        $router = $this->router();
        $router->define('POST', '/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_map_a_custom_method()
    {
        $this->mockRequest('CUSTOM', 'http://example.com/');

        $router = $this->router();
        $router->define('CUSTOM', '/', [SampleController::class, 'home']);
        $router->dispatch();

        $this->assertEquals('Home', $this->output($router));
    }

    /**
     * @throws Throwable
     */
    public function test_any_with_some_methods()
    {
        $router = $this->router();
        $router->any('/', function (ServerRequest $request) {
            return $request->getMethod();
        });

        $this->mockRequest('GET', 'http://example.com/');
        $router->dispatch();
        $this->assertEquals('GET', $this->output($router));

        $this->mockRequest('POST', 'http://example.com/');
        $router->dispatch();
        $this->assertEquals('POST', $this->output($router));
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Xml.Linq;

namespace cmtviswpf
{
    public class Answer
    {
        const string PLACEHOLDER = "REPLACE THIS WITH YOUR ANSWER";

        public List<TextBox> textboxes = new List<TextBox>();
        public List<RadioButton> radiobuttons = new List<RadioButton>();
        public List<CheckBox> checkboxes = new List<CheckBox>();
        public XElement element = null;

        public void setXML()
        {
            if (textboxes.Count > 0)
            {
                element.Value = textboxes[0].Text;
                return;
            }
            if (checkboxes.Count > 0)
            {
                element.Value = checkboxes[0].IsChecked == true ? "Yes" : "No";
                return;
            }
            bool found = false;
            foreach (RadioButton cb in radiobuttons)
            {
                if (cb.IsChecked == true)
                {
                    element.Value = (string)cb.Content;
                    found = true;
                    break;
                }
            }
            if (!found)
            {
                element.Value = PLACEHOLDER;
            }
        }

        public void setControl()
        {
            if (textboxes.Count > 0)
            {
                if (element.Value == PLACEHOLDER)
                {
                    textboxes[0].Text = "";
                }
                else
                {
                    textboxes[0].Text = element.Value;
                }
                return;
            }
            if (checkboxes.Count > 0)
            {
                checkboxes[0].IsChecked = element.Value == "Yes";
                return;
            }
            foreach (RadioButton cb in radiobuttons)
            {
                if (element.Value == PLACEHOLDER)
                {
                    cb.IsChecked = false;
                }
                else
                {
                    cb.IsChecked = element.Value == (string) cb.Content;
                }
            }
        }
    }
}


text:
namespace Rosalia.TaskLib.Svn
{
    public class SvnVersion
    {
        public SvnVersion(int number, string trail)
        {
            Number = number;
            Trail = trail;
        }

        /// <summary>
        /// Gets a revision number.
        /// </summary>
        public int Number { get; private set; }

        /// <summary>
        /// Gets a revision trailing string value. Could contain 'M', 'S', and 'P' chars.
        /// </summary>
        public string Trail { get; private set; }
    }
}


text:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed><tipo>Rua</tipo><logradouro>Jaraguá</logradouro><bairro>Estação</bairro><cidade>Araucária</cidade><uf>PR</uf><cep>83705040</cep></feed>


text:
package org.apache.mina.filter.codec;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.mina.core.buffer.IoBuffer;

/**
 * A {@link ProtocolEncoderOutput} based on queue.
 *
 * @author Apache MINA Project
 */
public abstract class AbstractProtocolEncoderOutput implements ProtocolEncoderOutput {
    private final Queue<Object> messageQueue = new ConcurrentLinkedQueue<Object>();

    private boolean buffersOnly = true;

    public AbstractProtocolEncoderOutput() {
        // Do nothing
    }

    public Queue<Object> getMessageQueue() {
        return messageQueue;
    }

    public void write(Object encodedMessage) {
        if (encodedMessage instanceof IoBuffer) {
            IoBuffer buf = (IoBuffer) encodedMessage;
            if (buf.hasRemaining()) {
                messageQueue.offer(buf);
            } else {
                throw new IllegalArgumentException("buf is empty. Forgot to call flip()?");
            }
        } else {
            messageQueue.offer(encodedMessage);
            buffersOnly = false;
        }
    }

    public void mergeAll() {
        if (!buffersOnly) {
            throw new IllegalStateException("the encoded message list contains a non-buffer.");
        }

        final int size = messageQueue.size();

        if (size < 2) {
            // no need to merge!
            return;
        }

        // Get the size of merged BB
        int sum = 0;
        for (Object b : messageQueue) {
            sum += ((IoBuffer) b).remaining();
        }

        // Allocate a new BB that will contain all fragments
        IoBuffer newBuf = IoBuffer.allocate(sum);

        // and merge all.
        for (;;) {
            IoBuffer buf = (IoBuffer) messageQueue.poll();
            if (buf == null) {
                break;
            }

            newBuf.put(buf);
        }

        // Push the new buffer finally.
        newBuf.flip();
        messageQueue.add(newBuf);
    }
}


text:
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][codecov-image]][codecov-url]
[![David deps][david-image]][david-url]
[![npm download][download-image]][download-url]

[npm-image]: https://img.shields.io/npm/v/easywebpack-cli.svg?style=flat-square
[npm-url]: https://npmjs.org/package/easywebpack-cli
[travis-image]: https://img.shields.io/travis/easy-team/easywebpack-cli.svg?style=flat-square
[travis-url]: https://travis-ci.org/easy-team/easywebpack-cli
[codecov-image]: https://codecov.io/gh/easy-team/easywebpack-cli/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/easy-team/easywebpack-cli
[david-image]: https://img.shields.io/david/easy-team/easywebpack-cli.svg?style=flat-square
[david-url]: https://david-dm.org/easy-team/easywebpack-cli
[download-image]: https://img.shields.io/npm/dm/easywebpack-cli.svg?style=flat-square
[download-url]: https://npmjs.org/package/easywebpack-cli

A Powerful Cross-platform Webpack CLI Tool

## Installation

- easywebpack-cli@5 -> easywebpack@5 (>=Node 8 + Babel 7)

```bash
npm i easywebpack-cli@4 -g
```

- @easy-team/easywebpack-cli@4 -> @easy-team/easywebpack@4 (>=Node 6 + Babel 7)

```bash
npm i @easy-team/easywebpack-cli -g
```

- easywebpack-cli@4 -> easywebpack@4 (>=Node 6 + Babel 6)

```bash
npm i easywebpack-cli -g
```

## Features

- ✔ Provide easywebpack and webapck development and build capabilities
- ✔ Provide multiple types of project initialization, such as React, Vue, Egg projects
- ✔ Provide multiple types of project builds, such as React, Vue, Egg, Weex projects
- ✔ Provide webpack basic development and build capabilities, such as dev server, hot-reload, typescript, dll
- ✔ Enhance Webpack-based development and build capabilities, such as build speed, build size capabilities
- ✔ Provide [easywebpack](https://github.com/easy-team/easywebpack) solution development and build capabilities
- ✔ Built-in normal development commands, such easy clean, easy open, easy kill, easy server

## Documents

- [Webpack Solution](https://github.com/easy-team/easywebpack)
- [Vue Single Application](https://github.com/easy-team/easywebpack-vue)
- [React Single Application](https://github.com/easy-team/easywebpack-react)
- [Vue Server Side Render](https://www.yuque.com/easy-team/ves)
- [React Server Side Render](https://www.yuque.com/easy-team/res)
- [Weex Application](https://github.com/easy-team/easywebpack-weex)

## Command

Support easywebpack and webpack modes,default easywebpack mode, you can specify the wepback build mode by `--webpack`. Default read `${root}/webpack.config.js` webpack config file.

- easywebpack mode: use easywebpack webpack config
- Webpack mode: use native webpack config

```bash
easy -h
```

Usage: easy [command] [options]

  Options:

    -v, --version          output the version number
    -f, --filename [path]  webpack config file path
    -p, --port [port]      webpack server port
    -s, --size [option]    webpack build size analyzer tool, support size: analyzer and stats, default analyzer
    --dll                  only webpack dll config
    --web                  only webpack web config
    --node                 only webpack node config
    --speed                stat webpack build speed
    --devtool [devtool]    webpack devtool config
    -h, --help             output usage information

  Commands:

    init [options]         init webpack config or boilerplate for Vue/React/Weex
    install [options]      dynamic install easywebpack missing npm module
    upgrade [options]      upgrade project package to latest version
    print [options] [env]  print webpack config, support print by env or config node key
    dll [env]              webpack dll build
    build [options] [env]  webpack building
    server [options]       static file web http server
    dev [env]              start webpack dev server for develoment mode
    start [env]            start webpack dev server for develoment mode
    zip [options]          archive files to zip file
    tar [options]          archive files to tar file
    deploy                 upload file to deplay space
    upgrade                upgrade webpack and npm package
    clean [dir]            webpack cache dir clean, if dir == "all", will clean cache dir and build dir
    open [dir]             open webpack cache dir
    kill [port]            kill port process, default will kill 7001, 9000, 9001

### Project Initialization

- easy init

> step one:

![step one](/doc/easy-init-step-one.png)

> step two:

![step two](/doc/easy-init-step-two.png)

### Add Component/Config

![easy add](/doc/easy-add.png)

#### 从列表中选择指定模板

```bash
easy add
```

#### 从列表中选择 React 相关模板

```bash
easy add --template react
```

#### 直接初始化模板

```bash
easy add --template react-component
```

#### 自定义模板路径/文件名

```bash
easy add --template react-component --dist src/components --output Test.jsx
```

### Project Development

#### easywebpack

- easy dev

- easy dev -f build/webpack.config.js

#### webpack

- easy dev --webpack

- easy dev -f build/webpack.config.js --webpack

### Project Building

#### easywebpack

- easy build prod

- easy build -f build/webpack.config.js

#### webpack

- easy build -f build/webpack.config.js --webpack

### Upgrade

- upgrade webpack3 to webpack4

```bash
easy upgrade
```

- upgrade egg project to webpack4

```bash
easy upgrade --egg
```

- upgrade babel 6 to babel 7

```bash
easy upgrade --babel
```

### Puppeteer Html Prerender

```bash
easy puppeteer --url http://49.233.172.37:7001/csr
```

### Clean Cache

```bash
easy clean
```

### Open Directory

```bash
easy open
```

### Kill Port

```bash
easy kill 7001
easy kill 7001,9000,9001
```

### Webpack Build Size

![easy-build-s](/doc/easy-build-s-cmd.png)

> https://www.yuque.com/easy-team/easywebpack/pdwchd

- webpack-bundle-analyzer

```bash
easy build -s
```

- stats-webpack-plugin

```bash
easy build -s stats
```

### Webpack Build Speed

Use the plugin `speed-measure-webpack-plugin` for build speed analysis and count the time spent on each loader and plugin

```bash
easy build --speed
```

### Start Web HTTP Server

Use the plugin `node-http-server` for local directory compilation access, automatically find HTML files

![easy server](/doc/easy-server-cmd.png)

- serve current dir

```bash
easy server
```

- serve specify port and directory

```bash
easy server -p 8888 -d dist
```

### Print Webpack Config Info

```bash
easy print -h
```

  Usage: print [env] [options]

    print webpack config, support print by env or config node key

  Options:

    -k, --key [name]  print webpack config info by config key name, example: [module/module.rules/plugins] and so on
    -h, --help        output usage information

- easy print -k module

- easy print dev -k entry

- easy print test -k module.rules

- easy print prod -k module.rules[0]

- easy print -k plugins

- easy print -k plugins[0]

- easy print -k output

- easy print -k resolve

## Extend Webpack CLI

- [res-cli](https://github.com/easy-team/res-cli) Res Node Web Framework Command CLI

- [ves-cli](https://github.com/easy-team/res-cli) Ves Node Web Framework Command CLI

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

sky
💻 📖

jasonjcpeng
💻 📖

Kevin Zhong
💻 📖

HiuYanChong
💻 📖

Mice
💻

hacke2
💻

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

## License

[MIT](LICENSE)


text:
namespace BotBits.Events
{
    /// <summary>
    ///     Occurs when a player's flying status changes
    /// </summary>
    public sealed class FlyEvent : Event<FlyEvent>
    {
        internal FlyEvent(Player player, bool flying)
        {
            this.Player = player;
            this.Flying = flying;
        }

        public Player Player { get; private set; }
        public bool Flying { get; private set; }
    }
}


text:
// Copyright 2015 The Bazel Authors. 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.
package com.google.devtools.build.lib.flags;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Verify;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.AllowValues;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.DisallowValues;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.FlagPolicy;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.FlagPolicy.OperationCase;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.SetValue;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.UseDefault;
import com.google.devtools.common.options.OptionPriority;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParser.OptionDescription;
import com.google.devtools.common.options.OptionsParser.OptionValueDescription;
import com.google.devtools.common.options.OptionsParsingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
 * Enforces the {@link FlagPolicy}s (from an {@link InvocationPolicy} proto) on an
 * {@link OptionsParser} by validating and changing the flag values in the given
 * {@link OptionsParser}.
 *
 *
"Flag" and "Option" are used interchangeably in this file.
 */
public final class InvocationPolicyEnforcer {

  private static final Logger log = Logger.getLogger(InvocationPolicyEnforcer.class.getName());

  private static final Function<Object, String> INVOCATION_POLICY_SOURCE =
      Functions.constant("Invocation policy");

  @Nullable private final InvocationPolicy invocationPolicy;

  /**
   * Creates an InvocationPolicyEnforcer that enforces the given policy.
   *
   * @param invocationPolicy the policy to enforce. A null policy means this enforcer will do
   *     nothing in calls to enforce().
   */
  public InvocationPolicyEnforcer(@Nullable InvocationPolicy invocationPolicy) {
    this.invocationPolicy = invocationPolicy;
  }

  public InvocationPolicy getInvocationPolicy() {
    return invocationPolicy;
  }

  /**
   * Applies this OptionsPolicyEnforcer's policy to the given OptionsParser for all blaze commands.
   *
   * @param parser The OptionsParser to enforce policy on.
   * @throws OptionsParsingException if any flag policy is invalid.
   */
  public void enforce(OptionsParser parser) throws OptionsParsingException {
    enforce(parser, null);
  }

  /**
   * Applies this OptionsPolicyEnforcer's policy to the given OptionsParser.
   *
   * @param parser The OptionsParser to enforce policy on.
   * @param command The current blaze command, for flag policies that apply to only specific
   *     commands. Such policies will be enforced only if they contain this command or a command
   *     they inherit from
   * @throws OptionsParsingException if any flag policy is invalid.
   */
  public void enforce(OptionsParser parser, @Nullable String command)
      throws OptionsParsingException {
    if (invocationPolicy == null || invocationPolicy.getFlagPoliciesCount() == 0) {
      return;
    }

    // The effective policy returned is expanded, filtered for applicable commands, and cleaned of
    // redundancies and conflicts.
    List<FlagPolicy> effectivePolicy = getEffectivePolicy(invocationPolicy, parser, command);

    for (FlagPolicy flagPolicy : effectivePolicy) {
      String flagName = flagPolicy.getFlagName();

      OptionValueDescription valueDescription;
      try {
        valueDescription = parser.getOptionValueDescription(flagName);
      } catch (IllegalArgumentException e) {
        // This flag doesn't exist. We are deliberately lenient if the flag policy has a flag
        // we don't know about. This is for better future proofing so that as new flags are added,
        // new policies can use the new flags without worrying about older versions of Bazel.
        log.info(
            String.format("Flag '%s' specified by invocation policy does not exist", flagName));
        continue;
      }

      OptionDescription optionDescription = parser.getOptionDescription(flagName);
      // getOptionDescription() will return null if the option does not exist, however
      // getOptionValueDescription() above would have thrown an IllegalArgumentException if that
      // were the case.
      Verify.verifyNotNull(optionDescription);

      switch (flagPolicy.getOperationCase()) {
        case SET_VALUE:
          applySetValueOperation(parser, flagPolicy, flagName, valueDescription, optionDescription);
          break;

        case USE_DEFAULT:
          applyUseDefaultOperation(parser, "UseDefault", flagName);
          break;

        case ALLOW_VALUES:
          AllowValues allowValues = flagPolicy.getAllowValues();
          FilterValueOperation.ALLOW_VALUE_OPERATION.apply(
              parser,
              allowValues.getAllowedValuesList(),
              allowValues.hasNewValue() ? allowValues.getNewValue() : null,
              allowValues.hasUseDefault(),
              flagName,
              valueDescription,
              optionDescription);
          break;

        case DISALLOW_VALUES:
          DisallowValues disallowValues = flagPolicy.getDisallowValues();
          FilterValueOperation.DISALLOW_VALUE_OPERATION.apply(
              parser,
              disallowValues.getDisallowedValuesList(),
              disallowValues.hasNewValue() ? disallowValues.getNewValue() : null,
              disallowValues.hasUseDefault(),
              flagName,
              valueDescription,
              optionDescription);
          break;

        case OPERATION_NOT_SET:
          throw new PolicyOperationNotSetException(flagName);

        default:
          log.warning(
              String.format(
                  "Unknown operation '%s' from invocation policy for flag '%s'",
                  flagPolicy.getOperationCase(),
                  flagName));
          break;
      }
    }
  }

  private static class PolicyOperationNotSetException extends OptionsParsingException {
    PolicyOperationNotSetException(String flagName) {
      super(String.format("Flag policy for flag '%s' does not " + "have an operation", flagName));
    }
  }

  private static boolean policyApplies(FlagPolicy policy, ImmutableSet<String> applicableCommands) {
    // Skip the flag policy if it doesn't apply to this command. If the commands list is empty,
    // then the policy applies to all commands.
    if (policy.getCommandsList().isEmpty() || applicableCommands.isEmpty()) {
      return true;
    }

    return !Collections.disjoint(policy.getCommandsList(), applicableCommands);
  }

  /**
   * Takes the provided policy and processes it to the form that can be used on the user options.
   *
   *
Expands any policies on expansion flags.
   */
  public static List<FlagPolicy> getEffectivePolicy(
      InvocationPolicy invocationPolicy, OptionsParser parser, String command)
      throws OptionsParsingException {
    if (invocationPolicy == null) {
      return ImmutableList.of();
    }

    ImmutableSet<String> commandAndParentCommands =
        command == null
            ? ImmutableSet.<String>of()
            : CommandNameCache.CommandNameCacheInstance.INSTANCE.get(command);

    // Expand all policies to transfer policies on expansion flags to policies on the child flags.
    List<FlagPolicy> expandedPolicies = new ArrayList<>();
    for (FlagPolicy policy : invocationPolicy.getFlagPoliciesList()) {
      if (!policyApplies(policy, commandAndParentCommands)) {
        // Only keep and expand policies that are applicable to the current command.
        continue;
      }
      List<FlagPolicy> policies = expandPolicy(policy, parser);
      expandedPolicies.addAll(policies);
    }

    // Only keep that last policy for each flag.
    Map<String, FlagPolicy> effectivePolicy = new HashMap<>();
    for (FlagPolicy expandedPolicy : expandedPolicies) {
      String flagName = expandedPolicy.getFlagName();
      effectivePolicy.put(flagName, expandedPolicy);
    }

    return new ArrayList<>(effectivePolicy.values());
  }

  /**
   * Expand a single policy. If the policy is not about an expansion flag, this will simply return a
   * list with a single element, oneself. If the policy is for an expansion flag, the policy will
   * get split into multiple policies applying to each flag the original flag expands to.
   *
   *
None of the flagPolicies returned should be on expansion flags.
   */
  private static List<FlagPolicy> expandPolicy(
      FlagPolicy originalPolicy,
      OptionsParser parser)
      throws OptionsParsingException {
    List<FlagPolicy> expandedPolicy = new ArrayList<>();

    OptionDescription originalDesc = parser.getOptionDescription(originalPolicy.getFlagName());
    if (originalDesc == null) {
      // InvocationPolicy ignores policy on non-existing flags by design, for version compatibility.
      return expandedPolicy;
    }

    ImmutableList.Builder<OptionValueDescription> subflagBuilder = new ImmutableList.Builder<>();
    ImmutableList<OptionValueDescription> subflags =
        subflagBuilder
            .addAll(originalDesc.getImplicitRequirements())
            .addAll(originalDesc.getExpansions())
            .build();
    boolean isExpansion = !originalDesc.getExpansions().isEmpty();

    if (!subflags.isEmpty() && log.isLoggable(Level.FINE)) {
      // Log the expansion. Since this is logged regardless of user provided command line, it is
      // only really useful for understanding the invocation policy itself. Most of the time,
      // invocation policy does not change, so this can be a log level fine.
      List<String> subflagNames = new ArrayList<>(subflags.size());
      for (OptionValueDescription subflag : subflags) {
        subflagNames.add("--" + subflag.getName());
      }

      log.logp(Level.FINE,
          "InvocationPolicyEnforcer",
          "expandPolicy",
          String.format(
            "Expanding %s on option %s to its %s: %s.",
            originalPolicy.getOperationCase(),
            originalPolicy.getFlagName(),
            isExpansion ? "expansions" : "implied flags",
            Joiner.on("; ").join(subflagNames)));
    }

    // Repeated flags are special, and could set multiple times in an expansion, with the user
    // expecting both values to be valid. Collect these separately.
    Multimap<String, OptionValueDescription> repeatableSubflagsInSetValues =
        ArrayListMultimap.create();

    // Create a flag policy for the child that looks like the parent's policy "transferred" to its
    // child. Note that this only makes sense for SetValue, when setting an expansion flag, or
    // UseDefault, when preventing it from being set.
    for (OptionValueDescription currentSubflag : subflags) {
      if (currentSubflag.getAllowMultiple()
          && originalPolicy.getOperationCase().equals(OperationCase.SET_VALUE)) {
        repeatableSubflagsInSetValues.put(currentSubflag.getName(), currentSubflag);
      } else {
        FlagPolicy subflagAsPolicy = getSubflagAsPolicy(
            currentSubflag, originalPolicy, originalDesc);
        // In case any of the expanded flags are themselves expansions, recurse.
        expandedPolicy.addAll(expandPolicy(subflagAsPolicy, parser));
      }
    }

    // If there are any repeatable flag SetValues, deal with them together now.
    // Note that expansion flags have no value, and so cannot have multiple values either.
    // Skipping the recursion above is fine.
    for (String repeatableFlag : repeatableSubflagsInSetValues.keySet()) {
      int numValues = repeatableSubflagsInSetValues.get(repeatableFlag).size();
      ArrayList<String> newValues = new ArrayList<>(numValues);
      for (OptionValueDescription setValue : repeatableSubflagsInSetValues.get(repeatableFlag)) {
        newValues.add(setValue.getOriginalValueString());
      }
      expandedPolicy.add(
          getSetValueSubflagAsPolicy(
              repeatableFlag,
              newValues,
              /* allowMultiple */ true,
              originalPolicy));

    }

    // Don't add the original policy if it was an expansion flag, which have no value, but do add
    // it if there was either no expansion or if it was a valued flag with implicit requirements.
    if (!isExpansion) {
      expandedPolicy.add(originalPolicy);
    }

    return expandedPolicy;
  }

  /**
   * Expand a SetValue flag policy on a repeatable flag. SetValue operations are the only flag
   * policies that set the flag, and so interact with repeatable flags, flags that can be set
   * multiple times, in subtle ways.
   *
   * @param subflagName, the flag the SetValue'd expansion flag expands to.
   * @param subflagValue, the values that the SetValue'd expansion flag expands to for this flag.
   * @param allowMultiple, whether the flag is multivalued.
   * @param originalPolicy, the original policy on the expansion flag.
   * @return the flag policy for the subflag given, this will be part of the expanded form of the
   *  SetValue policy on the original flag.
   */
  private static FlagPolicy getSetValueSubflagAsPolicy(
      String subflagName,
      List<String> subflagValue,
      boolean allowMultiple,
      FlagPolicy originalPolicy) {
    // Some sanity checks.
    Verify.verify(originalPolicy.getOperationCase().equals(OperationCase.SET_VALUE));
    if (!allowMultiple) {
      Verify.verify(subflagValue.size() <= 1);
    }

    // Flag value from the expansion, overridability from the original policy, unless the flag is
    // repeatable, in which case we care about appendability, not overridability.
    SetValue.Builder setValueExpansion = SetValue.newBuilder();
    for (String value : subflagValue) {
      setValueExpansion.addFlagValue(value);
    }
    if (allowMultiple) {
      setValueExpansion.setAppend(originalPolicy.getSetValue().getOverridable());
    } else {
      setValueExpansion.setOverridable(originalPolicy.getSetValue().getOverridable());
    }

    // Commands from the original policy, flag name of the expansion
    return FlagPolicy.newBuilder()
            .addAllCommands(originalPolicy.getCommandsList())
            .setFlagName(subflagName)
            .setSetValue(setValueExpansion)
            .build();
  }

  /**
   * For an expansion flag in an invocation policy, each flag it expands to must be given a
   * corresponding policy.
   */
  private static FlagPolicy getSubflagAsPolicy(
      OptionValueDescription currentSubflag,
      FlagPolicy originalPolicy,
      OptionDescription originalDesc) throws OptionsParsingException {
    boolean isExpansion = !originalDesc.getExpansions().isEmpty();
    FlagPolicy subflagAsPolicy = null;
    switch (originalPolicy.getOperationCase()) {
      case SET_VALUE:
        assert(!currentSubflag.getAllowMultiple());
        subflagAsPolicy = getSetValueSubflagAsPolicy(
            currentSubflag.getName(),
            ImmutableList.of(currentSubflag.getOriginalValueString()),
            /* allowMultiple */ false,
            originalPolicy);
        break;

      case USE_DEFAULT:
        // Commands from the original policy, flag name of the expansion
        subflagAsPolicy =
            FlagPolicy.newBuilder()
                .addAllCommands(originalPolicy.getCommandsList())
                .setFlagName(currentSubflag.getName())
                .setUseDefault(
                    UseDefault
                        .getDefaultInstance())
                .build();
        break;

      case ALLOW_VALUES:
        if (isExpansion) {
          throw new OptionsParsingException(
              String.format(
                  "Allow_Values on expansion flags like %s is not allowed.",
                  originalPolicy.getFlagName()));
        }
        // If this flag is an implicitRequirement, and some values for the parent flag are
        // allowed, nothing needs to happen on the implicitRequirement that is set for all
        // values of the flag.
        break;

      case DISALLOW_VALUES:
        if (isExpansion) {
          throw new OptionsParsingException(
              String.format(
                  "Disallow_Values on expansion flags like %s is not allowed.",
                  originalPolicy.getFlagName()));
        }
        // If this flag is an implicitRequirement, and some values for the parent flag are
        // disallowed, that implies that all others are allowed, so nothing needs to happen
        // on the implicitRequirement that is set for all values of the parent flag.
        break;

      case OPERATION_NOT_SET:
        throw new PolicyOperationNotSetException(originalPolicy.getFlagName());

      default:
        return null;
    }
    return subflagAsPolicy;
  }

  private static void logInApplySetValueOperation(String formattingString, Object... objects) {
    // Finding the caller here is relatively expensive and shows up in profiling, so provide it
    // manually.
    log.logp(
        Level.INFO,
        "InvocationPolicyEnforcer",
        "applySetValueOperation",
        String.format(formattingString, objects));
  }

  private static void applySetValueOperation(
      OptionsParser parser,
      FlagPolicy flagPolicy,
      String flagName,
      OptionValueDescription valueDescription,
      OptionDescription optionDescription)
      throws OptionsParsingException {

    SetValue setValue = flagPolicy.getSetValue();

    // SetValue.flag_value must have at least 1 value.
    if (setValue.getFlagValueCount() == 0) {
      throw new OptionsParsingException(
          String.format(
              "SetValue operation from invocation policy for flag '%s' does not have a value",
              flagName));
    }

    // Flag must allow multiple values if multiple values are specified by the policy.
    if (setValue.getFlagValueCount() > 1 && !optionDescription.getAllowMultiple()) {
      throw new OptionsParsingException(
          String.format(
              "SetValue operation from invocation policy sets multiple values for flag '%s' which "
                  + "does not allow multiple values",
              flagName));
    }

    if (setValue.getOverridable() && valueDescription != null) {
      // The user set the value for the flag but the flag policy is overridable, so keep the user's
      // value.
      logInApplySetValueOperation(
          "Keeping value '%s' from source '%s' for flag '%s' "
              + "because the invocation policy specifying the value(s) '%s' is overridable",
          valueDescription.getValue(),
          valueDescription.getSource(),
          flagName,
          setValue.getFlagValueList());
    } else {

      if (!setValue.getAppend()) {
        // Clear the value in case the flag is a repeated flag so that values don't accumulate.
        parser.clearValue(flagName);
      }

      // Set all the flag values from the policy.
      for (String flagValue : setValue.getFlagValueList()) {
        if (valueDescription == null) {
          logInApplySetValueOperation(
              "Setting value for flag '%s' from invocation "
                  + "policy to '%s', overriding the default value '%s'",
              flagName, flagValue, optionDescription.getDefaultValue());
        } else {
          logInApplySetValueOperation(
              "Setting value for flag '%s' from invocation "
                  + "policy to '%s', overriding value '%s' from '%s'",
              flagName, flagValue, valueDescription.getValue(), valueDescription.getSource());
        }
        setFlagValue(parser, flagName, flagValue);
      }
    }
  }

  private static void applyUseDefaultOperation(
      OptionsParser parser, String policyType, String flagName) throws OptionsParsingException {
    OptionValueDescription clearedValueDescription = parser.clearValue(flagName);
    if (clearedValueDescription != null) {
      // Log the removed value.
      String clearedFlagName = clearedValueDescription.getName();
      String originalValue = clearedValueDescription.getValue().toString();
      String source = clearedValueDescription.getSource();

      OptionDescription desc = parser.getOptionDescription(clearedFlagName);
      Object clearedFlagDefaultValue = null;
      if (desc != null) {
        clearedFlagDefaultValue = desc.getDefaultValue();
      }
      log.info(
          String.format(
              "Using default value '%s' for flag '%s' as "
                  + "specified by %s invocation policy, overriding original value '%s' from '%s'",
              clearedFlagDefaultValue,
              clearedFlagName,
              policyType,
              originalValue,
              source));
    }
  }

  /**
   * Checks the user's flag values against a filtering function.
   */
  private abstract static class FilterValueOperation {

    private static final FilterValueOperation ALLOW_VALUE_OPERATION =
        new FilterValueOperation("Allow") {
          @Override
          boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value) {
            return convertedPolicyValues.contains(value);
          }
        };

    private static final FilterValueOperation DISALLOW_VALUE_OPERATION =
        new FilterValueOperation("Disallow") {
          @Override
          boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value) {
            // In a disallow operation, the values that the flag policy specifies are not allowed,
            // so the value is allowed if the set of policy values does not contain the current
            // flag value.
            return !convertedPolicyValues.contains(value);
          }
        };

    private final String policyType;

    FilterValueOperation(String policyType) {
      this.policyType = policyType;
    }

    /**
     * Determines if the given value is allowed.
     *
     * @param convertedPolicyValues The values given from the FlagPolicy, converted to real objects.
     * @param value The user value of the flag.
     * @return True if the value should be allowed, false if it should not.
     */
    abstract boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value);

    void apply(
        OptionsParser parser,
        List<String> policyValues,
        String newValue,
        boolean useDefault,
        String flagName,
        OptionValueDescription valueDescription,
        OptionDescription optionDescription)
        throws OptionsParsingException {

      // Convert all the allowed values from strings to real objects using the options'
      // converters so that they can be checked for equality using real .equals() instead
      // of string comparison. For example, "--foo=0", "--foo=false", "--nofoo", and "-f-"
      // (if the option has an abbreviation) are all equal for boolean flags. Plus converters
      // can be arbitrarily complex.
      Set<Object> convertedPolicyValues = Sets.newHashSet();
      for (String value : policyValues) {
        Object convertedValue = optionDescription.getConverter().convert(value);
        // Some converters return lists, and if the flag is a repeatable flag, the items in the
        // list from the converter should be added, and not the list itself. Otherwise the items
        // from invocation policy will be compared to lists, which will never work.
        // See OptionsParserImpl.ParsedOptionEntry.addValue.
        if (optionDescription.getAllowMultiple() && convertedValue instanceof List<?>) {
          convertedPolicyValues.addAll((List<?>) convertedValue);
        } else {
          convertedPolicyValues.add(optionDescription.getConverter().convert(value));
        }
      }

      // Check that if the default value of the flag is disallowed by the policy, that the policy
      // does not also set use_default. Otherwise the default value would will still be set if the
      // user uses a disallowed value. This doesn't apply to repeatable flags since the default
      // value for repeatable flags is always the empty list.
      if (!optionDescription.getAllowMultiple()) {

        boolean defaultValueAllowed =
            isFlagValueAllowed(convertedPolicyValues, optionDescription.getDefaultValue());
        if (!defaultValueAllowed && useDefault) {
          throw new OptionsParsingException(
              String.format(
                  "%sValues policy disallows the default value '%s' for flag '%s' but also "
                      + "specifies to use the default value",
                  policyType,
                  optionDescription.getDefaultValue(),
                  flagName));
        }
      }

      if (valueDescription == null) {
        // Nothing has set the value yet, so check that the default value from the flag's
        // definition is allowed. The else case below (i.e. valueDescription is not null) checks for
        // the flag allowing multiple values, however, flags that allow multiple values cannot have
        // default values, and their value is always the empty list if they haven't been specified,
        // which is why new_default_value is not a repeated field.
        checkDefaultValue(
            parser,
            policyValues,
            newValue,
            flagName,
            optionDescription,
            convertedPolicyValues);
      } else {
        checkUserValue(
            parser,
            policyValues,
            newValue,
            useDefault,
            flagName,
            valueDescription,
            optionDescription,
            convertedPolicyValues);
      }
    }

    void checkDefaultValue(
        OptionsParser parser,
        List<String> policyValues,
        String newValue,
        String flagName,
        OptionDescription optionDescription,
        Set<Object> convertedPolicyValues)
        throws OptionsParsingException {

      if (!isFlagValueAllowed(convertedPolicyValues, optionDescription.getDefaultValue())) {
        if (newValue != null) {
          // Use the default value from the policy.
          log.info(
              String.format(
                  "Overriding default value '%s' for flag '%s' with value '%s' "
                      + "specified by invocation policy. %sed values are: %s",
                  optionDescription.getDefaultValue(),
                  flagName,
                  newValue,
                  policyType,
                  policyValues));
          parser.clearValue(flagName);
          setFlagValue(parser, flagName, newValue);
        } else {
          // The operation disallows the default value, but doesn't supply a new value.
          throw new OptionsParsingException(
              String.format(
                  "Default flag value '%s' for flag '%s' is not allowed by invocation policy, but "
                      + "the policy does not provide a new value. "
                      + "%sed values are: %s",
                  optionDescription.getDefaultValue(),
                  flagName,
                  policyType,
                  policyValues));
        }
      }
    }

    void checkUserValue(
        OptionsParser parser,
        List<String> policyValues,
        String newValue,
        boolean useDefault,
        String flagName,
        OptionValueDescription valueDescription,
        OptionDescription optionDescription,
        Set<Object> convertedPolicyValues)
        throws OptionsParsingException {

      if (optionDescription.getAllowMultiple()) {
        // allowMultiple requires that the type of the option be List<T>, so cast from Object
        // to List<?>.
        List<?> optionValues = (List<?>) valueDescription.getValue();
        for (Object value : optionValues) {
          if (!isFlagValueAllowed(convertedPolicyValues, value)) {
            if (useDefault) {
              applyUseDefaultOperation(parser, policyType + "Values", flagName);
            } else {
              throw new OptionsParsingException(
                  String.format(
                      "Flag value '%s' for flag '%s' is not allowed by invocation policy. "
                          + "%sed values are: %s",
                      value,
                      flagName,
                      policyType,
                      policyValues));
            }
          }
        }

      } else {

        if (!isFlagValueAllowed(convertedPolicyValues, valueDescription.getValue())) {
          if (newValue != null) {
            log.info(
                String.format(
                    "Overriding disallowed value '%s' for flag '%s' with value '%s' "
                        + "specified by invocation policy. %sed values are: %s",
                    valueDescription.getValue(),
                    flagName,
                    newValue,
                    policyType,
                    policyValues));
            parser.clearValue(flagName);
            setFlagValue(parser, flagName, newValue);
          } else if (useDefault) {
            applyUseDefaultOperation(parser, policyType + "Values", flagName);
          } else {
            throw new OptionsParsingException(
                String.format(
                    "Flag value '%s' for flag '%s' is not allowed by invocation policy and the "
                        + "policy does not specify a new value. %sed values are: %s",
                    valueDescription.getValue(),
                    flagName,
                    policyType,
                    policyValues));
          }
        }
      }
    }
  }

  private static void setFlagValue(OptionsParser parser, String flagName, String flagValue)
      throws OptionsParsingException {

    parser.parseWithSourceFunction(
        OptionPriority.INVOCATION_POLICY,
        INVOCATION_POLICY_SOURCE,
        Arrays.asList(String.format("--%s=%s", flagName, flagValue)));
  }
}


text:
using System.Xml.Serialization;
using OXStack.Data;
using OXStack.Config;

namespace OXStack
{
    /// <summary>
    /// Basic class with basic functions
    /// </summary>
    public class Base : IBaseBare
    {
        private DataConnector _dc = null;
        /// <summary>
        /// DataConnector class
        /// </summary>
        [XmlIgnore]
        public DataConnector DataConnector { get { return _dc ?? (_dc = new DataConnector()); } set { _dc = value; } }

        // caching..
        private CachingHelper _ch = null;
        /// <summary>
        /// Cache. 4 hours standard
        /// </summary>
        [XmlIgnore]
        public CachingHelper Cache { get { return _ch ?? (_ch = new CachingHelper(60 * 4)); } }

        // config
        private OXConfig _cfg = null;
        /// <summary>
        /// Configuration
        /// </summary>
        [XmlIgnore]
        public OXConfig Config { get { return _cfg ?? (_cfg = new OXConfig()); } }

        /// <summary>
        /// Raw destructor.
        /// </summary>
        ~Base()
        {
            if (_dc != null)
            {
                _dc.Dispose();
                _dc = null;
            }
            if (_ch != null)
                _ch = null;
            if (_cfg != null)
                _cfg = null;
        }
    }

}


text:
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"

#include <memory>

#include "base/memory/scoped_refptr.h"
#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/client/gles2_interface_stub.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h"
#include "third_party/blink/renderer/platform/graphics/test/gpu_memory_buffer_test_platform.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "ui/gl/gpu_preference.h"
#include "v8/include/v8.h"

using testing::Test;
using testing::_;

namespace blink {

MATCHER_P(SyncTokenEq, token, "") {
  return *reinterpret_cast<const gpu::SyncToken*>(arg) == token;
}

class DrawingBufferTest : public Test {
 protected:
  void SetUp() override { Init(kDisableMultisampling); }

  void Init(UseMultisampling use_multisampling) {
    gfx::Size initial_size(kInitialWidth, kInitialHeight);
    auto gl = std::make_unique<GLES2InterfaceForTests>();
    auto provider =
        std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl));
    GLES2InterfaceForTests* gl_ =
        static_cast<GLES2InterfaceForTests*>(provider->ContextGL());
    Platform::GraphicsInfo graphics_info;
    graphics_info.using_gpu_compositing = true;
    drawing_buffer_ = DrawingBufferForTests::Create(
        std::move(provider), graphics_info, gl_, initial_size,
        DrawingBuffer::kPreserve, use_multisampling);
    CHECK(drawing_buffer_);
    SetAndSaveRestoreState(false);
  }

  // Initialize GL state with unusual values, to verify that they are restored.
  // The |invert| parameter will reverse all boolean parameters, so that all
  // values are tested.
  void SetAndSaveRestoreState(bool invert) {
    GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
    GLboolean scissor_enabled = !invert;
    GLfloat clear_color[4] = {0.1, 0.2, 0.3, 0.4};
    GLfloat clear_depth = 0.8;
    GLint clear_stencil = 37;
    GLboolean color_mask[4] = {invert, !invert, !invert, invert};
    GLboolean depth_mask = invert;
    GLboolean stencil_mask = invert;
    GLint pack_alignment = 7;
    GLuint active_texture2d_binding = 0xbeef1;
    GLuint renderbuffer_binding = 0xbeef2;
    GLuint draw_framebuffer_binding = 0xbeef3;
    GLuint read_framebuffer_binding = 0xbeef4;
    GLuint pixel_unpack_buffer_binding = 0xbeef5;

    if (scissor_enabled)
      gl_->Enable(GL_SCISSOR_TEST);
    else
      gl_->Disable(GL_SCISSOR_TEST);

    gl_->ClearColor(clear_color[0], clear_color[1], clear_color[2],
                    clear_color[3]);
    gl_->ClearDepthf(clear_depth);
    gl_->ClearStencil(clear_stencil);
    gl_->ColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
    gl_->DepthMask(depth_mask);
    gl_->StencilMask(stencil_mask);
    gl_->PixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
    gl_->BindTexture(GL_TEXTURE_2D, active_texture2d_binding);
    gl_->BindRenderbuffer(GL_RENDERBUFFER, renderbuffer_binding);
    gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_framebuffer_binding);
    gl_->BindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer_binding);
    gl_->BindBuffer(GL_PIXEL_UNPACK_BUFFER, pixel_unpack_buffer_binding);

    gl_->SaveState();
  }

  void VerifyStateWasRestored() {
    GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
    gl_->VerifyStateHasNotChangedSinceSave();
  }

  scoped_refptr<DrawingBufferForTests> drawing_buffer_;
};

class DrawingBufferTestMultisample : public DrawingBufferTest {
 protected:
  void SetUp() override { Init(kEnableMultisampling); }
};

TEST_F(DrawingBufferTestMultisample, verifyMultisampleResolve) {
  // Initial state: already marked changed, multisampled
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->ExplicitResolveOfMultisampleData());

  // Resolve the multisample buffer
  drawing_buffer_->ResolveAndBindForReadAndDraw();

  // After resolve, acknowledge new content
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  // No new content
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());

  drawing_buffer_->BeginDestruction();
}

TEST_F(DrawingBufferTest, VerifyResizingProperlyAffectsResources) {
  viz::TestSharedImageInterface* sii =
      drawing_buffer_->SharedImageInterfaceForTests();

  VerifyStateWasRestored();
  viz::TransferableResource resource;
  viz::ReleaseCallback release_callback;

  gfx::Size initial_size(kInitialWidth, kInitialHeight);
  gfx::Size alternate_size(kInitialWidth, kAlternateHeight);

  // Produce one resource at size 100x100.
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  VerifyStateWasRestored();
  EXPECT_EQ(initial_size, sii->MostRecentSize());

  // Resize to 100x50.
  drawing_buffer_->Resize(alternate_size);
  VerifyStateWasRestored();
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  VerifyStateWasRestored();

  // Produce a resource at this size.
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(alternate_size, sii->MostRecentSize());
  VerifyStateWasRestored();

  // Reset to initial size.
  drawing_buffer_->Resize(initial_size);
  VerifyStateWasRestored();
  SetAndSaveRestoreState(true);
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  VerifyStateWasRestored();

  // Prepare another resource and verify that it's the correct size.
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(initial_size, sii->MostRecentSize());
  VerifyStateWasRestored();

  // Prepare one final resource and verify that it's the correct size.
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  VerifyStateWasRestored();
  EXPECT_EQ(initial_size, sii->MostRecentSize());
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  drawing_buffer_->BeginDestruction();
}

TEST_F(DrawingBufferTest, VerifySharedImagesReleasedAfterReleaseCallback) {
  auto* sii = drawing_buffer_->SharedImageInterfaceForTests();

  viz::TransferableResource resource1;
  viz::ReleaseCallback release_callback1;
  viz::TransferableResource resource2;
  viz::ReleaseCallback release_callback2;
  viz::TransferableResource resource3;
  viz::ReleaseCallback release_callback3;

  // Produce resources.
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  drawing_buffer_->ClearFramebuffers(GL_STENCIL_BUFFER_BIT);
  VerifyStateWasRestored();
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource1,
                                                           &release_callback1));
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  drawing_buffer_->ClearFramebuffers(GL_DEPTH_BUFFER_BIT);
  VerifyStateWasRestored();
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2,
                                                           &release_callback2));
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  drawing_buffer_->ClearFramebuffers(GL_COLOR_BUFFER_BIT);
  VerifyStateWasRestored();
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3,
                                                           &release_callback3));

  EXPECT_EQ(sii->shared_image_count(), 4u);

  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  std::move(release_callback1).Run(gpu::SyncToken(), true /* lostResource */);
  EXPECT_EQ(sii->shared_image_count(), 3u);

  std::move(release_callback2).Run(gpu::SyncToken(), true /* lostResource */);
  EXPECT_EQ(sii->shared_image_count(), 2u);

  // The resource is not marked lost so it's recycled after the callback.
  std::move(release_callback3).Run(gpu::SyncToken(), false /* lostResource */);
  EXPECT_EQ(sii->shared_image_count(), 2u);

  drawing_buffer_->BeginDestruction();
}

TEST_F(DrawingBufferTest, VerifyCachedRecycledResourcesAreKept) {
  const size_t kNumResources = DrawingBuffer::kDefaultColorBufferCacheLimit + 1;
  std::vector<viz::TransferableResource> resources(kNumResources);
  std::vector<viz::ReleaseCallback> release_callbacks(kNumResources);

  // Produce resources.
  for (size_t i = 0; i < kNumResources; ++i) {
    drawing_buffer_->MarkContentsChanged();
    EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(
        nullptr, &resources[i], &release_callbacks[i]));
  }

  // Release resources.
  for (auto& release_callback : release_callbacks) {
    drawing_buffer_->MarkContentsChanged();
    std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  }

  std::vector<viz::ReleaseCallback> recycled_release_callbacks(
      DrawingBuffer::kDefaultColorBufferCacheLimit);

  // The first recycled resource must be from the cache
  for (size_t i = 0; i < DrawingBuffer::kDefaultColorBufferCacheLimit; ++i) {
    viz::TransferableResource recycled_resource;
    viz::ReleaseCallback recycled_release_callback;
    drawing_buffer_->MarkContentsChanged();
    EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(
        nullptr, &recycled_resource, &recycled_release_callbacks[i]));

    bool recycled = false;
    for (auto& resource : resources) {
      if (recycled_resource.mailbox_holder.mailbox ==
          resource.mailbox_holder.mailbox) {
        recycled = true;
        break;
      }
    }
    EXPECT_TRUE(recycled);
  }

  // The next recycled resource must be a new resource.
  viz::TransferableResource next_recycled_resource;
  viz::ReleaseCallback next_recycled_release_callback;
  drawing_buffer_->MarkContentsChanged();
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(
      nullptr, &next_recycled_resource, &next_recycled_release_callback));
  for (auto& resource : resources) {
    EXPECT_NE(resource.mailbox_holder.mailbox,
              next_recycled_resource.mailbox_holder.mailbox);
  }
  recycled_release_callbacks.push_back(
      std::move(next_recycled_release_callback));

  // Cleanup
  for (auto& release_cb : recycled_release_callbacks) {
    std::move(release_cb).Run(gpu::SyncToken(), false /* lostResource */);
  }
  drawing_buffer_->BeginDestruction();
}

TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncTokenCorrectly) {
  GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
  viz::TransferableResource resource;
  viz::ReleaseCallback release_callback;

  // Produce resources.
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));

  // Pretend to release the resource. We should not wait for the sync token yet
  // because the returned buffer is not recycled.
  gpu::SyncToken wait_sync_token;
  gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData());
  EXPECT_CALL(*gl_, WaitSyncTokenCHROMIUMMock(SyncTokenEq(wait_sync_token)))
      .Times(0);
  std::move(release_callback).Run(wait_sync_token, false /* lostResource */);
  testing::Mock::VerifyAndClearExpectations(gl_);

  // The returned buffer will be recycled in PrepareTransferrableResource. Make
  // sure we wait for the sync token now.
  EXPECT_CALL(*gl_, WaitSyncTokenCHROMIUMMock(SyncTokenEq(wait_sync_token)))
      .Times(1);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  testing::Mock::VerifyAndClearExpectations(gl_);

  // Release the resource and begin destruction. We will not wait on the sync
  // token because the buffer is not reused. SharedImageInterface, however, will
  // wait on the sync token before destruction.
  gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData());
  EXPECT_CALL(*gl_, WaitSyncTokenCHROMIUMMock(SyncTokenEq(wait_sync_token)))
      .Times(0);
  std::move(release_callback).Run(wait_sync_token, false /* lostResource */);
  drawing_buffer_->BeginDestruction();
  testing::Mock::VerifyAndClearExpectations(gl_);
}

class DrawingBufferImageChromiumTest : public DrawingBufferTest,
                                       private ScopedWebGLImageChromiumForTest {
 public:
  DrawingBufferImageChromiumTest() : ScopedWebGLImageChromiumForTest(true) {}

 protected:
  void SetUp() override {
    platform_ = std::make_unique<
        ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform>>();

    gfx::Size initial_size(kInitialWidth, kInitialHeight);
    auto gl = std::make_unique<GLES2InterfaceForTests>();
    auto provider =
        std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl));
    GLES2InterfaceForTests* gl_ =
        static_cast<GLES2InterfaceForTests*>(provider->ContextGL());
    EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
    Platform::GraphicsInfo graphics_info;
    graphics_info.using_gpu_compositing = true;
    drawing_buffer_ = DrawingBufferForTests::Create(
        std::move(provider), graphics_info, gl_, initial_size,
        DrawingBuffer::kPreserve, kDisableMultisampling);
    CHECK(drawing_buffer_);
    SetAndSaveRestoreState(true);
    testing::Mock::VerifyAndClearExpectations(gl_);
  }

  void TearDown() override {
    platform_.reset();
  }

  GLuint image_id0_;
  std::unique_ptr<ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform>>
      platform_;
};

TEST_F(DrawingBufferImageChromiumTest, VerifyResizingReallocatesImages) {
  GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
  viz::TestSharedImageInterface* sii =
      drawing_buffer_->SharedImageInterfaceForTests();

  viz::TransferableResource resource;
  viz::ReleaseCallback release_callback;

  gfx::Size initial_size(kInitialWidth, kInitialHeight);
  gfx::Size alternate_size(kInitialWidth, kAlternateHeight);

  // There should be currently one back buffer and therefore one SharedImage.
  gpu::Mailbox mailbox1;
  mailbox1.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(1u, sii->shared_image_count());
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox1));

  // Produce one resource at size 100x100. This should create another buffer and
  // therefore another SharedImage.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(initial_size, sii->MostRecentSize());
  EXPECT_TRUE(resource.is_overlay_candidate);
  EXPECT_EQ(initial_size, resource.size);
  testing::Mock::VerifyAndClearExpectations(gl_);
  VerifyStateWasRestored();
  gpu::Mailbox mailbox2;
  mailbox2.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox1));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox2));
  EXPECT_EQ(mailbox2, resource.mailbox_holder.mailbox);

  // Resize to 100x50. The current backbuffer must be destroyed. The exported
  // resource should stay alive. A new backbuffer must be created.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  drawing_buffer_->Resize(alternate_size);
  VerifyStateWasRestored();
  gpu::Mailbox mailbox3;
  mailbox3.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox1));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox2));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox3));
  testing::Mock::VerifyAndClearExpectations(gl_);

  // Return the exported resource. Now it should get destroyed too.
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  VerifyStateWasRestored();
  EXPECT_EQ(1u, sii->shared_image_count());
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox1));
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox2));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox3));

  // Produce a resource at the new size.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(alternate_size, sii->MostRecentSize());
  EXPECT_TRUE(resource.is_overlay_candidate);
  EXPECT_EQ(alternate_size, resource.size);
  gpu::Mailbox mailbox4;
  mailbox4.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox3));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox4));
  EXPECT_EQ(mailbox4, resource.mailbox_holder.mailbox);
  testing::Mock::VerifyAndClearExpectations(gl_);

  // Reset to initial size. The exported resource has to stay alive, but the
  // current back buffer must be destroyed and a new one with the right size
  // must be created.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  drawing_buffer_->Resize(initial_size);
  VerifyStateWasRestored();
  gpu::Mailbox mailbox5;
  mailbox5.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox3));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox4));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox5));
  testing::Mock::VerifyAndClearExpectations(gl_);

  // Return the exported resource. Now it will be destroyed too.
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  VerifyStateWasRestored();
  EXPECT_EQ(1u, sii->shared_image_count());
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox3));
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox4));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox5));

  // Prepare another resource and verify that it's the correct size.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(initial_size, sii->MostRecentSize());
  EXPECT_TRUE(resource.is_overlay_candidate);
  EXPECT_EQ(initial_size, resource.size);
  testing::Mock::VerifyAndClearExpectations(gl_);
  gpu::Mailbox mailbox6;
  mailbox6.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox5));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox6));

  // Prepare one final resource and verify that it's the correct size. We should
  // recycle the previously exported resource and avoid allocating a new
  // SharedImage.
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));
  EXPECT_EQ(initial_size, sii->MostRecentSize());
  EXPECT_TRUE(resource.is_overlay_candidate);
  EXPECT_EQ(initial_size, resource.size);
  std::move(release_callback).Run(gpu::SyncToken(), false /* lostResource */);
  EXPECT_EQ(2u, sii->shared_image_count());
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox5));
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox6));

  drawing_buffer_->BeginDestruction();
  testing::Mock::VerifyAndClearExpectations(sii);
  EXPECT_EQ(0u, sii->shared_image_count());
}

TEST_F(DrawingBufferImageChromiumTest, AllocationFailure) {
  GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
  viz::TestGpuMemoryBufferManager* gmb_manager =
      static_cast<viz::TestGpuMemoryBufferManager*>(
          Platform::Current()->GetGpuMemoryBufferManager());
  viz::TestSharedImageInterface* sii =
      drawing_buffer_->SharedImageInterfaceForTests();

  viz::TransferableResource resource1;
  viz::ReleaseCallback release_callback1;
  viz::TransferableResource resource2;
  viz::ReleaseCallback release_callback2;
  viz::TransferableResource resource3;
  viz::ReleaseCallback release_callback3;

  // Request a resource. A SharedImage should already be created. Everything
  // works as expected.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource1,
                                                           &release_callback1));
  EXPECT_TRUE(resource1.is_overlay_candidate);
  gpu::Mailbox mailbox1;
  mailbox1.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox1));
  testing::Mock::VerifyAndClearExpectations(gl_);
  VerifyStateWasRestored();

  // Force GpuMemoryBuffer creation failure. Request another resource. It should
  // still be provided, but this time with allowOverlay = false.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  gmb_manager->SetFailOnCreate(true);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2,
                                                           &release_callback2));
  EXPECT_FALSE(resource2.is_overlay_candidate);
  gpu::Mailbox mailbox2;
  mailbox2.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox2));
  VerifyStateWasRestored();

  // Check that if GpuMemoryBuffer allocation starts working again, resources
  // are correctly created with allowOverlay = true.
  EXPECT_CALL(*gl_, CreateAndTexStorage2DSharedImageCHROMIUMMock(_)).Times(1);
  gmb_manager->SetFailOnCreate(false);
  EXPECT_TRUE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3,
                                                           &release_callback3));
  EXPECT_TRUE(resource3.is_overlay_candidate);
  gpu::Mailbox mailbox3;
  mailbox3.SetName(gl_->last_imported_shared_image()->name);
  EXPECT_TRUE(sii->CheckSharedImageExists(mailbox3));
  testing::Mock::VerifyAndClearExpectations(gl_);
  VerifyStateWasRestored();

  std::move(release_callback1).Run(gpu::SyncToken(), false /* lostResource */);
  std::move(release_callback2).Run(gpu::SyncToken(), false /* lostResource */);
  std::move(release_callback3).Run(gpu::SyncToken(), false /* lostResource */);

  drawing_buffer_->BeginDestruction();
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox1));
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox2));
  EXPECT_FALSE(sii->CheckSharedImageExists(mailbox3));
}

class DepthStencilTrackingGLES2Interface
    : public gpu::gles2::GLES2InterfaceStub {
 public:
  void FramebufferRenderbuffer(GLenum target,
                               GLenum attachment,
                               GLenum renderbuffertarget,
                               GLuint renderbuffer) override {
    switch (attachment) {
      case GL_DEPTH_ATTACHMENT:
        depth_attachment_ = renderbuffer;
        break;
      case GL_STENCIL_ATTACHMENT:
        stencil_attachment_ = renderbuffer;
        break;
      case GL_DEPTH_STENCIL_ATTACHMENT:
        depth_stencil_attachment_ = renderbuffer;
        break;
      default:
        NOTREACHED();
        break;
    }
  }

  GLenum CheckFramebufferStatus(GLenum target) override {
    return GL_FRAMEBUFFER_COMPLETE;
  }

  void GetIntegerv(GLenum ptype, GLint* value) override {
    switch (ptype) {
      case GL_MAX_TEXTURE_SIZE:
        *value = 1024;
        return;
    }
  }

  const GLubyte* GetString(GLenum type) override {
    if (type == GL_EXTENSIONS)
      return reinterpret_cast<const GLubyte*>("GL_OES_packed_depth_stencil");
    return reinterpret_cast<const GLubyte*>("");
  }

  void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override {
    for (GLsizei i = 0; i < n; ++i)
      renderbuffers[i] = next_gen_renderbuffer_id_++;
  }

  GLuint StencilAttachment() const { return stencil_attachment_; }
  GLuint DepthAttachment() const { return depth_attachment_; }
  GLuint DepthStencilAttachment() const { return depth_stencil_attachment_; }
  size_t NumAllocatedRenderBuffer() const {
    return next_gen_renderbuffer_id_ - 1;
  }

 private:
  GLuint next_gen_renderbuffer_id_ = 1;
  GLuint depth_attachment_ = 0;
  GLuint stencil_attachment_ = 0;
  GLuint depth_stencil_attachment_ = 0;
};

struct DepthStencilTestCase {
  DepthStencilTestCase(bool request_stencil,
                       bool request_depth,
                       int expected_render_buffers,
                       const char* const test_case_name)
      : request_stencil(request_stencil),
        request_depth(request_depth),
        expected_render_buffers(expected_render_buffers),
        test_case_name(test_case_name) {}

  bool request_stencil;
  bool request_depth;
  size_t expected_render_buffers;
  const char* const test_case_name;
};

// This tests that, when the packed depth+stencil extension is supported, and
// either depth or stencil is requested, DrawingBuffer always allocates a single
// packed renderbuffer and properly computes the actual context attributes as
// defined by WebGL. We always allocate a packed buffer in this case since many
// desktop OpenGL drivers that support this extension do not consider a
// framebuffer with only a depth or a stencil buffer attached to be complete.
TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) {
  DepthStencilTestCase cases[] = {
      DepthStencilTestCase(false, false, 0, "neither"),
      DepthStencilTestCase(true, false, 1, "stencil only"),
      DepthStencilTestCase(false, true, 1, "depth only"),
      DepthStencilTestCase(true, true, 1, "both"),
  };

  for (size_t i = 0; i < std::size(cases); i++) {
    SCOPED_TRACE(cases[i].test_case_name);
    auto gl = std::make_unique<DepthStencilTrackingGLES2Interface>();
    DepthStencilTrackingGLES2Interface* tracking_gl = gl.get();
    auto provider =
        std::make_unique<WebGraphicsContext3DProviderForTests>(std::move(gl));
    DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::kPreserve;

    Platform::GraphicsInfo graphics_info;
    graphics_info.using_gpu_compositing = true;
    bool premultiplied_alpha = false;
    bool want_alpha_channel = true;
    bool want_depth_buffer = cases[i].request_depth;
    bool want_stencil_buffer = cases[i].request_stencil;
    bool want_antialiasing = false;
    bool using_swap_chain = false;
    bool desynchronized = false;
    scoped_refptr<DrawingBuffer> drawing_buffer = DrawingBuffer::Create(
        std::move(provider), graphics_info, using_swap_chain, nullptr,
        gfx::Size(10, 10), premultiplied_alpha, want_alpha_channel,
        want_depth_buffer, want_stencil_buffer, want_antialiasing,
        desynchronized, preserve, DrawingBuffer::kWebGL1,
        DrawingBuffer::kAllowChromiumImage, cc::PaintFlags::FilterQuality::kLow,
        PredefinedColorSpace::kSRGB, CanvasPixelFormat::kUint8,
        gl::GpuPreference::kHighPerformance);

    // When we request a depth or a stencil buffer, we will get both.
    EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil,
              drawing_buffer->HasDepthBuffer());
    EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil,
              drawing_buffer->HasStencilBuffer());
    EXPECT_EQ(cases[i].expected_render_buffers,
              tracking_gl->NumAllocatedRenderBuffer());
    if (cases[i].request_depth || cases[i].request_stencil) {
      EXPECT_NE(0u, tracking_gl->DepthStencilAttachment());
      EXPECT_EQ(0u, tracking_gl->DepthAttachment());
      EXPECT_EQ(0u, tracking_gl->StencilAttachment());
    } else {
      EXPECT_EQ(0u, tracking_gl->DepthStencilAttachment());
      EXPECT_EQ(0u, tracking_gl->DepthAttachment());
      EXPECT_EQ(0u, tracking_gl->StencilAttachment());
    }

    drawing_buffer->Resize(gfx::Size(10, 20));
    EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil,
              drawing_buffer->HasDepthBuffer());
    EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil,
              drawing_buffer->HasStencilBuffer());
    EXPECT_EQ(cases[i].expected_render_buffers,
              tracking_gl->NumAllocatedRenderBuffer());
    if (cases[i].request_depth || cases[i].request_stencil) {
      EXPECT_NE(0u, tracking_gl->DepthStencilAttachment());
      EXPECT_EQ(0u, tracking_gl->DepthAttachment());
      EXPECT_EQ(0u, tracking_gl->StencilAttachment());
    } else {
      EXPECT_EQ(0u, tracking_gl->DepthStencilAttachment());
      EXPECT_EQ(0u, tracking_gl->DepthAttachment());
      EXPECT_EQ(0u, tracking_gl->StencilAttachment());
    }

    drawing_buffer->BeginDestruction();
  }
}

TEST_F(DrawingBufferTest, VerifySetIsHiddenProperlyAffectsMailboxes) {
  GLES2InterfaceForTests* gl_ = drawing_buffer_->ContextGLForTests();
  viz::TransferableResource resource;
  viz::ReleaseCallback release_callback;

  // Produce resources.
  EXPECT_FALSE(drawing_buffer_->MarkContentsChanged());
  EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource,
                                                           &release_callback));

  gpu::SyncToken wait_sync_token;
  gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData());
  drawing_buffer_->SetIsInHiddenPage(true);
  // m_drawingBuffer deletes resource immediately when hidden.
  EXPECT_CALL(*gl_, WaitSyncTokenCHROMIUMMock(SyncTokenEq(wait_sync_token)))
      .Times(0);
  std::move(release_callback).Run(wait_sync_token, false /* lostResource */);
  testing::Mock::VerifyAndClearExpectations(gl_);

  drawing_buffer_->BeginDestruction();
}

TEST_F(DrawingBufferTest,
       VerifyTooBigDrawingBufferExceedingV8MaxSizeFailsToCreate) {
  gfx::Size too_big_size(1, (v8::TypedArray::kMaxLength / 4) + 1);
  Platform::GraphicsInfo graphics_info;
  graphics_info.using_gpu_compositing = true;
  scoped_refptr<DrawingBuffer> too_big_drawing_buffer = DrawingBuffer::Create(
      nullptr, graphics_info, false /* using_swap_chain */, nullptr,
      too_big_size, false, false, false, false, false, /*desynchronized=*/false,
      DrawingBuffer::kDiscard, DrawingBuffer::kWebGL1,
      DrawingBuffer::kAllowChromiumImage, cc::PaintFlags::FilterQuality::kLow,
      PredefinedColorSpace::kSRGB, CanvasPixelFormat::kUint8,
      gl::GpuPreference::kHighPerformance);
  EXPECT_EQ(too_big_drawing_buffer, nullptr);
  drawing_buffer_->BeginDestruction();
}

}  // namespace blink


text:
layout: post
title: How To Use VMware Station?
---

tutrial For Mrs.Huang
1.install linux system
   1.1 you need VMware Station software
   1.2 linux ios
   1.3 install the ios system in your VM
2.instal tools
   2.1 use the VMtools software in your system
   2.2 share files with linux system and the window system.
   setup the VM to open share folds function

   Quetions List

   how to install tools
   cann't find the shared folds in linux system /mnt/hgfs

   upstart failed to connect
   	sudo dpkg-divert --local --rename --add /sbin/initctl
   	ln -s /bin/true /sbin/initctl


text:
package net.amham.odfe.difference;

public class DocumentDifference {
	//this can be done like the enum radius and something example

	public enum DiffType {CHANGED, ADDED, MISSING};
	private DiffType difftype = DiffType.CHANGED;

	protected String name;
	protected String detail;

	public DocumentDifference(DiffType type) {
		difftype = type;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDetail() {
		return detail;
	}

	public void setDetail(String detail) {
		this.detail = detail;
	}

	public DiffType getType() {
		return difftype;
	}
}


text:
package com.ityang.leetcode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Subject229 {

	public static void main(String[] args) {
		System.out.println(majorityElement(new int[]{2,2}));
	}
	public static List<Integer> majorityElement(int[] nums) {
		List<Integer> res = new ArrayList<>();
		Map<Integer,Integer> map = new HashMap<>();
		int bound = (int) Math.floor(nums.length/3.0);
		for(int i=0;i<nums.length;i++){
			if(map.containsKey(nums[i])){
				if(map.get(nums[i])>=bound){
					res.add(nums[i]);
					map.put(nums[i], Integer.MIN_VALUE);
				}
				else
					map.put(nums[i],1+map.get(nums[i]));
			}else{
				map.put(nums[i], 1);
				if(1>bound){
					res.add(nums[i]);
					map.put(nums[i], Integer.MIN_VALUE);
				}
			}
		}
		return res;
	}
}


text:
/// <reference path="../Scripts/jquery-2.0.3.min.js" />
/// <reference path="../Scripts/jquery.blockUI.min.js" />
/// <reference path="../Scripts/jQuery.tmpl.min.js" />

/// <reference path="../Scripts/AsyncRequest.Queue.js" />
/// <reference path="../Scripts/AsyncRequest.js" />

describe("Queue Execute", function () {
    var request;
    var objRequest;
    var timeOutRequest = 30;
    var configBase = { notification: { notifyFunction: false } };
    beforeEach(function () {
        request = $.asyncRequest;

        //objRequest = request.getObjAsync();
        spyOn($, "ajax").andCallFake(function (params) {
            setTimeout(function () { params.success('opa'); params.complete("Be Nice!!!"); }, timeOutRequest);

        });
    });

    it("Um request deve ser feitos apos o outro, usando a mesma chave", function () {
        var queueKey = "someKey";
        runs(function () {
            var count = 0;
            for (var i = 0; i < 10; i++) {
                objRequest = request.getObjAsync();
                objRequest.Queue = queueKey;
                objRequest.SuccessFunction = function (data) {
                    if (count == 0)
                        count = new Date().getTime();
                    else {
                        count = new Date().getTime() - count;
                        //console.log(count);
                        expect(count).toBeGreaterThan(timeOutRequest);
                    }
                }
                request.get(objRequest);
            }
        });

        waits(10 * timeOutRequest);

        runs(function () {
            expect(true).toBe(true);
        });

    });

    it("Com Queues diferentes(\"keys\") os request devem ser concorrentes entre as chaves", function () {

        for (var queueKey = 0; queueKey < 10; queueKey++) {
            for (var i = 0; i < 10; i++) {
                objRequest = request.getObjAsync();
                objRequest.Queue = queueKey;
                //Assim força a copia da variavel
                SetaURLFORACONTEXT(objRequest, queueKey.toString());
                request.get(objRequest);
            }

            waits(11 * timeOutRequest);
        }

        runs(function () {
            expect(true).toBe(true);
        });

    });

});

function SetaURLFORACONTEXT(objRequest, url) {
    objRequest.Url = url;
    objRequest.SuccessFunction = function (data) {
        //console.log(url);
    }
}

/*
describe("Block Element", function () {
    var request;
    var objRequest;
    beforeEach(function () {
        request = Object.create($.asyncRequest);
        objRequest = request.getObjAsync();
        spyOn($, "ajax").andCallFake(function (params) {
            setTimeout(function () { params.success('opa') }, 5);
            //    params.error("Sad Face");
            //    params.complete("Be Nice!!!");
        });
    });

    afterEach(function () {
        //
    });

    it("Com sucesso", function () {
        $("body").append("

Laga

")
        objRequest.Containner = $("#area");
        objRequest.Msg = "LAGA LAGA LAGA";
        objRequest.SuccessFunction = function (data) {
            $("#teste").remove();
        }
        request.get(objRequest);
        var valor = $("#teste").find(".blockElement").text();
        expect(valor).toBe(objRequest.Msg);
    });

});
*/