<commit_before>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.

	The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
*/
/** @file RPCSession.cpp
 * @author Dimtiry Khokhlov <dimitry@ethdev.com>
 * @author Alex Beregszaszi
 * @date 2016
 */

#include <string>
#include <stdio.h>
#include <thread>
#include <libdevcore/CommonData.h>
#include <json/reader.h>
#include <json/writer.h>
#include "RPCSession.h"

using namespace std;
using namespace dev;

IPCSocket::IPCSocket(string const& _path): m_path(_path)
{
#if defined(_WIN32)
	m_socket = CreateFile(
		m_path.c_str(),   // pipe name
		GENERIC_READ |  // read and write access
		GENERIC_WRITE,
		0,              // no sharing
		NULL,           // default security attribute
		OPEN_EXISTING,  // opens existing pipe
		0,              // default attributes
		NULL);          // no template file

	if (m_socket == INVALID_HANDLE_VALUE)
		BOOST_FAIL("Error creating IPC socket object!");

#else
	if (_path.length() >= sizeof(sockaddr_un::sun_path))
		BOOST_FAIL("Error opening IPC: socket path is too long!");

	struct sockaddr_un saun;
	memset(&saun, 0, sizeof(sockaddr_un));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, _path.c_str());

// http://idletechnology.blogspot.ca/2011/12/unix-domain-sockets-on-osx.html
//
// SUN_LEN() might be optimal, but it seemingly affects the portability,
// with at least Android missing this macro.  Just using the sizeof() for
// structure seemingly works, and would only have the side-effect of
// sending larger-than-required packets over the socket.  Given that this
// code is only used for unit-tests, that approach seems simpler.
#if defined(__APPLE__)
	saun.sun_len = sizeof(struct sockaddr_un);
#endif //  defined(__APPLE__)

	if ((m_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
		BOOST_FAIL("Error creating IPC socket object");

	if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0)
		BOOST_FAIL("Error connecting to IPC socket: " << _path);
#endif
}

string IPCSocket::sendRequest(string const& _req)
{
#if defined(_WIN32)
	string returnStr;
	DWORD cbWritten;
	BOOL fSuccess = WriteFile(
		m_socket,               // pipe handle
		_req.c_str(),           // message
		_req.size(),            // message length
		&cbWritten,             // bytes written
		NULL);                  // not overlapped

	if (!fSuccess)
		BOOST_FAIL("WriteFile to pipe failed");

	DWORD cbRead;

	// Read from the pipe.
	fSuccess = ReadFile(
		m_socket,          // pipe handle
		m_readBuf,         // buffer to receive reply
		sizeof(m_readBuf), // size of buffer
		&cbRead,           // number of bytes read
		NULL);             // not overlapped

	returnStr += m_readBuf;

	if (!fSuccess)
		BOOST_FAIL("ReadFile from pipe failed");

	return returnStr;
#else
	if (send(m_socket, _req.c_str(), _req.length(), 0) != (ssize_t)_req.length())
		BOOST_FAIL("Writing on IPC failed");

	ssize_t ret = recv(m_socket, m_readBuf, sizeof(m_readBuf), 0);

	// Also consider closed socket an error.
	if (ret <= 0)
		BOOST_FAIL("Reading on IPC failed");

	return string(m_readBuf, m_readBuf + ret);
#endif
}

RPCSession& RPCSession::instance(const string& _path)
{
	static RPCSession session(_path);
	BOOST_REQUIRE_EQUAL(session.m_ipcSocket.path(), _path);
	return session;
}

string RPCSession::eth_getCode(string const& _address, string const& _blockNumber)
{
	return rpcCall("eth_getCode", { quote(_address), quote(_blockNumber) }).asString();
}

RPCSession::TransactionReceipt RPCSession::eth_getTransactionReceipt(string const& _transactionHash)
{
	TransactionReceipt receipt;
	Json::Value const result = rpcCall("eth_getTransactionReceipt", { quote(_transactionHash) });
	BOOST_REQUIRE(!result.isNull());
	receipt.gasUsed = result["gasUsed"].asString();
	receipt.contractAddress = result["contractAddress"].asString();
	for (auto const& log: result["logs"])
	{
		LogEntry entry;
		entry.address = log["address"].asString();
		entry.data = log["data"].asString();
		for (auto const& topic: log["topics"])
			entry.topics.push_back(topic.asString());
		receipt.logEntries.push_back(entry);
	}
	return receipt;
}

string RPCSession::eth_sendTransaction(TransactionData const& _td)
{
	return rpcCall("eth_sendTransaction", { _td.toJson() }).asString();
}

string RPCSession::eth_call(TransactionData const& _td, string const& _blockNumber)
{
	return rpcCall("eth_call", { _td.toJson(), quote(_blockNumber) }).asString();
}

string RPCSession::eth_sendTransaction(string const& _transaction)
{
	return rpcCall("eth_sendTransaction", { _transaction }).asString();
}

string RPCSession::eth_getBalance(string const& _address, string const& _blockNumber)
{
	string address = (_address.length() == 20) ? "0x" + _address : _address;
	return rpcCall("eth_getBalance", { quote(address), quote(_blockNumber) }).asString();
}

string RPCSession::eth_getStorageRoot(string const& _address, string const& _blockNumber)
{
	string address = (_address.length() == 20) ? "0x" + _address : _address;
	return rpcCall("eth_getStorageRoot", { quote(address), quote(_blockNumber) }).asString();
}

void RPCSession::personal_unlockAccount(string const& _address, string const& _password, int _duration)
{
	BOOST_REQUIRE(rpcCall("personal_unlockAccount", { quote(_address), quote(_password), to_string(_duration) }) == true);
}

string RPCSession::personal_newAccount(string const& _password)
{
	return rpcCall("personal_newAccount", { quote(_password) }).asString();
}

void RPCSession::test_setChainParams(vector<string> const& _accounts)
{
	static std::string const c_configString = R"(
	{
		"sealEngine": "NoProof",
		"params": {
			"accountStartNonce": "0x",
			"maximumExtraDataSize": "0x1000000",
			"blockReward": "0x",
			"allowFutureBlocks": "1"
		},
		"genesis": {
			"author": "0000000000000010000000000000000000000000",
			"timestamp": "0x00",
			"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
			"extraData": "0x",
			"gasLimit": "0x1000000000000"
		},
		"accounts": {
			"0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } },
			"0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } },
			"0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } },
			"0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }
		}
	}
	)";

	Json::Value config;
	BOOST_REQUIRE(Json::Reader().parse(c_configString, config));
	for (auto const& account: _accounts)
		config["accounts"][account]["wei"] = "0x100000000000000000000000000000000000000000";
	test_setChainParams(Json::FastWriter().write(config));
}

void RPCSession::test_setChainParams(string const& _config)
{
	BOOST_REQUIRE(rpcCall("test_setChainParams", { _config }) == true);
}

void RPCSession::test_rewindToBlock(size_t _blockNr)
{
	BOOST_REQUIRE(rpcCall("test_rewindToBlock", { to_string(_blockNr) }) == true);
}

void RPCSession::test_mineBlocks(int _number)
{
	u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString()));
	BOOST_REQUIRE(rpcCall("test_mineBlocks", { to_string(_number) }, true) == true);

	bool mined = false;

	// We auto-calibrate the time it takes to mine the transaction.
	// It would be better to go without polling, but that would probably need a change to the test client

	unsigned sleepTime = m_sleepTime;
	size_t polls = 0;
	for (; polls < 14 && !mined; ++polls)
	{
		std::this_thread::sleep_for(chrono::milliseconds(sleepTime));
		if (fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) >= startBlock + _number)
			mined = true;
		else
			sleepTime *= 2;
	}
	if (polls > 1)
	{
		m_successfulMineRuns = 0;
		m_sleepTime += 2;
	}
	else if (polls == 1)
	{
		m_successfulMineRuns++;
		if (m_successfulMineRuns > 5)
		{
			m_successfulMineRuns = 0;
			if (m_sleepTime > 2)
				m_sleepTime--;
		}
	}

	if (!mined)
		BOOST_FAIL("Error in test_mineBlocks: block mining timeout!");
}

void RPCSession::test_modifyTimestamp(size_t _timestamp)
{
	BOOST_REQUIRE(rpcCall("test_modifyTimestamp", { to_string(_timestamp) }) == true);
}

Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& _args, bool _canFail)
{
	string request = "{\"jsonrpc\":\"2.0\",\"method\":\"" + _methodName + "\",\"params\":[";
	for (size_t i = 0; i < _args.size(); ++i)
	{
		request += _args[i];
		if (i + 1 != _args.size())
			request += ", ";
	}

	request += "],\"id\":" + to_string(m_rpcSequence) + "}";
	++m_rpcSequence;

	//cout << "Request: " << request << endl;
	string reply = m_ipcSocket.sendRequest(request);
	//cout << "Reply: " << reply << endl;

	Json::Value result;
	BOOST_REQUIRE(Json::Reader().parse(reply, result, false));

	if (result.isMember("error"))
	{
		if (_canFail)
			return Json::Value();

		BOOST_FAIL("Error on JSON-RPC call: " + result["error"]["message"].asString());
	}
	return result["result"];
}

string const& RPCSession::accountCreateIfNotExists(size_t _id)
{
	if (_id >= m_accounts.size())
	{
		m_accounts.push_back(personal_newAccount(""));
		personal_unlockAccount(m_accounts.back(), "", 100000);
	}
	return m_accounts[_id];
}

RPCSession::RPCSession(const string& _path):
	m_ipcSocket(_path)
{
	string account = personal_newAccount("");
	personal_unlockAccount(account, "", 100000);
	m_accounts.push_back(account);
	test_setChainParams(m_accounts);
}

string RPCSession::TransactionData::toJson() const
{
	Json::Value json;
	json["from"] = (from.length() == 20) ? "0x" + from : from;
	json["to"] = (to.length() == 20 || to == "") ? "0x" + to :  to;
	json["gas"] = gas;
	json["gasprice"] = gasPrice;
	json["value"] = value;
	json["data"] = data;
	return Json::FastWriter().write(json);

}
<commit_msg>Simplify the Windows IPC code<commit_after>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.

	The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
*/
/** @file RPCSession.cpp
 * @author Dimtiry Khokhlov <dimitry@ethdev.com>
 * @author Alex Beregszaszi
 * @date 2016
 */

#include <string>
#include <stdio.h>
#include <thread>
#include <libdevcore/CommonData.h>
#include <json/reader.h>
#include <json/writer.h>
#include "RPCSession.h"

using namespace std;
using namespace dev;

IPCSocket::IPCSocket(string const& _path): m_path(_path)
{
#if defined(_WIN32)
	m_socket = CreateFile(
		m_path.c_str(),   // pipe name
		GENERIC_READ |  // read and write access
		GENERIC_WRITE,
		0,              // no sharing
		NULL,           // default security attribute
		OPEN_EXISTING,  // opens existing pipe
		0,              // default attributes
		NULL);          // no template file

	if (m_socket == INVALID_HANDLE_VALUE)
		BOOST_FAIL("Error creating IPC socket object!");

#else
	if (_path.length() >= sizeof(sockaddr_un::sun_path))
		BOOST_FAIL("Error opening IPC: socket path is too long!");

	struct sockaddr_un saun;
	memset(&saun, 0, sizeof(sockaddr_un));
	saun.sun_family = AF_UNIX;
	strcpy(saun.sun_path, _path.c_str());

// http://idletechnology.blogspot.ca/2011/12/unix-domain-sockets-on-osx.html
//
// SUN_LEN() might be optimal, but it seemingly affects the portability,
// with at least Android missing this macro.  Just using the sizeof() for
// structure seemingly works, and would only have the side-effect of
// sending larger-than-required packets over the socket.  Given that this
// code is only used for unit-tests, that approach seems simpler.
#if defined(__APPLE__)
	saun.sun_len = sizeof(struct sockaddr_un);
#endif //  defined(__APPLE__)

	if ((m_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
		BOOST_FAIL("Error creating IPC socket object");

	if (connect(m_socket, reinterpret_cast<struct sockaddr const*>(&saun), sizeof(struct sockaddr_un)) < 0)
		BOOST_FAIL("Error connecting to IPC socket: " << _path);
#endif
}

string IPCSocket::sendRequest(string const& _req)
{
#if defined(_WIN32)
	// Write to the pipe.
	DWORD cbWritten;
	BOOL fSuccess = WriteFile(
		m_socket,               // pipe handle
		_req.c_str(),           // message
		_req.size(),            // message length
		&cbWritten,             // bytes written
		NULL);                  // not overlapped

	if (!fSuccess)
		BOOST_FAIL("WriteFile to pipe failed");

	// Read from the pipe.
	DWORD cbRead;
	fSuccess = ReadFile(
		m_socket,          // pipe handle
		m_readBuf,         // buffer to receive reply
		sizeof(m_readBuf), // size of buffer
		&cbRead,           // number of bytes read
		NULL);             // not overlapped

	if (!fSuccess)
		BOOST_FAIL("ReadFile from pipe failed");

	return string(m_readBuf, m_readBuf + cbRead);
#else
	if (send(m_socket, _req.c_str(), _req.length(), 0) != (ssize_t)_req.length())
		BOOST_FAIL("Writing on IPC failed");

	ssize_t ret = recv(m_socket, m_readBuf, sizeof(m_readBuf), 0);

	// Also consider closed socket an error.
	if (ret <= 0)
		BOOST_FAIL("Reading on IPC failed");

	return string(m_readBuf, m_readBuf + ret);
#endif
}

RPCSession& RPCSession::instance(const string& _path)
{
	static RPCSession session(_path);
	BOOST_REQUIRE_EQUAL(session.m_ipcSocket.path(), _path);
	return session;
}

string RPCSession::eth_getCode(string const& _address, string const& _blockNumber)
{
	return rpcCall("eth_getCode", { quote(_address), quote(_blockNumber) }).asString();
}

RPCSession::TransactionReceipt RPCSession::eth_getTransactionReceipt(string const& _transactionHash)
{
	TransactionReceipt receipt;
	Json::Value const result = rpcCall("eth_getTransactionReceipt", { quote(_transactionHash) });
	BOOST_REQUIRE(!result.isNull());
	receipt.gasUsed = result["gasUsed"].asString();
	receipt.contractAddress = result["contractAddress"].asString();
	for (auto const& log: result["logs"])
	{
		LogEntry entry;
		entry.address = log["address"].asString();
		entry.data = log["data"].asString();
		for (auto const& topic: log["topics"])
			entry.topics.push_back(topic.asString());
		receipt.logEntries.push_back(entry);
	}
	return receipt;
}

string RPCSession::eth_sendTransaction(TransactionData const& _td)
{
	return rpcCall("eth_sendTransaction", { _td.toJson() }).asString();
}

string RPCSession::eth_call(TransactionData const& _td, string const& _blockNumber)
{
	return rpcCall("eth_call", { _td.toJson(), quote(_blockNumber) }).asString();
}

string RPCSession::eth_sendTransaction(string const& _transaction)
{
	return rpcCall("eth_sendTransaction", { _transaction }).asString();
}

string RPCSession::eth_getBalance(string const& _address, string const& _blockNumber)
{
	string address = (_address.length() == 20) ? "0x" + _address : _address;
	return rpcCall("eth_getBalance", { quote(address), quote(_blockNumber) }).asString();
}

string RPCSession::eth_getStorageRoot(string const& _address, string const& _blockNumber)
{
	string address = (_address.length() == 20) ? "0x" + _address : _address;
	return rpcCall("eth_getStorageRoot", { quote(address), quote(_blockNumber) }).asString();
}

void RPCSession::personal_unlockAccount(string const& _address, string const& _password, int _duration)
{
	BOOST_REQUIRE(rpcCall("personal_unlockAccount", { quote(_address), quote(_password), to_string(_duration) }) == true);
}

string RPCSession::personal_newAccount(string const& _password)
{
	return rpcCall("personal_newAccount", { quote(_password) }).asString();
}

void RPCSession::test_setChainParams(vector<string> const& _accounts)
{
	static std::string const c_configString = R"(
	{
		"sealEngine": "NoProof",
		"params": {
			"accountStartNonce": "0x",
			"maximumExtraDataSize": "0x1000000",
			"blockReward": "0x",
			"allowFutureBlocks": "1"
		},
		"genesis": {
			"author": "0000000000000010000000000000000000000000",
			"timestamp": "0x00",
			"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
			"extraData": "0x",
			"gasLimit": "0x1000000000000"
		},
		"accounts": {
			"0000000000000000000000000000000000000001": { "wei": "1", "precompiled": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } },
			"0000000000000000000000000000000000000002": { "wei": "1", "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } },
			"0000000000000000000000000000000000000003": { "wei": "1", "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } },
			"0000000000000000000000000000000000000004": { "wei": "1", "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } }
		}
	}
	)";

	Json::Value config;
	BOOST_REQUIRE(Json::Reader().parse(c_configString, config));
	for (auto const& account: _accounts)
		config["accounts"][account]["wei"] = "0x100000000000000000000000000000000000000000";
	test_setChainParams(Json::FastWriter().write(config));
}

void RPCSession::test_setChainParams(string const& _config)
{
	BOOST_REQUIRE(rpcCall("test_setChainParams", { _config }) == true);
}

void RPCSession::test_rewindToBlock(size_t _blockNr)
{
	BOOST_REQUIRE(rpcCall("test_rewindToBlock", { to_string(_blockNr) }) == true);
}

void RPCSession::test_mineBlocks(int _number)
{
	u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString()));
	BOOST_REQUIRE(rpcCall("test_mineBlocks", { to_string(_number) }, true) == true);

	bool mined = false;

	// We auto-calibrate the time it takes to mine the transaction.
	// It would be better to go without polling, but that would probably need a change to the test client

	unsigned sleepTime = m_sleepTime;
	size_t polls = 0;
	for (; polls < 14 && !mined; ++polls)
	{
		std::this_thread::sleep_for(chrono::milliseconds(sleepTime));
		if (fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) >= startBlock + _number)
			mined = true;
		else
			sleepTime *= 2;
	}
	if (polls > 1)
	{
		m_successfulMineRuns = 0;
		m_sleepTime += 2;
	}
	else if (polls == 1)
	{
		m_successfulMineRuns++;
		if (m_successfulMineRuns > 5)
		{
			m_successfulMineRuns = 0;
			if (m_sleepTime > 2)
				m_sleepTime--;
		}
	}

	if (!mined)
		BOOST_FAIL("Error in test_mineBlocks: block mining timeout!");
}

void RPCSession::test_modifyTimestamp(size_t _timestamp)
{
	BOOST_REQUIRE(rpcCall("test_modifyTimestamp", { to_string(_timestamp) }) == true);
}

Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& _args, bool _canFail)
{
	string request = "{\"jsonrpc\":\"2.0\",\"method\":\"" + _methodName + "\",\"params\":[";
	for (size_t i = 0; i < _args.size(); ++i)
	{
		request += _args[i];
		if (i + 1 != _args.size())
			request += ", ";
	}

	request += "],\"id\":" + to_string(m_rpcSequence) + "}";
	++m_rpcSequence;

	//cout << "Request: " << request << endl;
	string reply = m_ipcSocket.sendRequest(request);
	//cout << "Reply: " << reply << endl;

	Json::Value result;
	BOOST_REQUIRE(Json::Reader().parse(reply, result, false));

	if (result.isMember("error"))
	{
		if (_canFail)
			return Json::Value();

		BOOST_FAIL("Error on JSON-RPC call: " + result["error"]["message"].asString());
	}
	return result["result"];
}

string const& RPCSession::accountCreateIfNotExists(size_t _id)
{
	if (_id >= m_accounts.size())
	{
		m_accounts.push_back(personal_newAccount(""));
		personal_unlockAccount(m_accounts.back(), "", 100000);
	}
	return m_accounts[_id];
}

RPCSession::RPCSession(const string& _path):
	m_ipcSocket(_path)
{
	string account = personal_newAccount("");
	personal_unlockAccount(account, "", 100000);
	m_accounts.push_back(account);
	test_setChainParams(m_accounts);
}

string RPCSession::TransactionData::toJson() const
{
	Json::Value json;
	json["from"] = (from.length() == 20) ? "0x" + from : from;
	json["to"] = (to.length() == 20 || to == "") ? "0x" + to :  to;
	json["gas"] = gas;
	json["gasprice"] = gasPrice;
	json["value"] = value;
	json["data"] = data;
	return Json::FastWriter().write(json);

}
<|endoftext|>


<commit_before>// BASIC TEST

#include <sstream>

#include "checker.h"

#include <gtest/gtest.h>

namespace sqlcheck {

TEST(BasicTest, RunChecker) {

  configuration default_conf;

  std::string queries =
      "SELECT *\n"
      "FROM FOO;\n"
      "\n"
      "SELECT *\n"
      "FROM BAR;\n";

  std::unique_ptr<std::istringstream> stream =
      std::make_unique<std::istringstream>(queries);

  default_conf.testing_mode = true;
  default_conf.test_stream.reset(stream.release());

  Check(default_conf);

}

}  // End machine sqlcheck
<commit_msg>Skip using make_unique<commit_after>// BASIC TEST

#include <sstream>

#include "checker.h"

#include <gtest/gtest.h>

namespace sqlcheck {

TEST(BasicTest, RunChecker) {

  configuration default_conf;
  default_conf.testing_mode = true;

  std::unique_ptr<std::istringstream> stream(new std::istringstream());
  stream->str(
      "SELECT *\n"
      "FROM FOO;\n"
      "\n"
      "SELECT *\n"
      "FROM BAR;\n"
      );

  default_conf.test_stream.reset(stream.release());

  Check(default_conf);

}

}  // End machine sqlcheck
<|endoftext|>


<commit_before>// Copyright (c) Team CharLS. All rights reserved. See the accompanying "LICENSE.md" for licensed use.

#include "compliance.h"
#include "util.h"

#include "../src/charls.h"

#include <iostream>
#include <vector>
#include <cstring>
#include <array>

using namespace charls;

namespace
{

void Triplet2Planar(std::vector<uint8_t>& rgbyte, Size size)
{
    std::vector<uint8_t> rgbytePlanar(rgbyte.size());

    const size_t cbytePlane = static_cast<size_t>(size.cx) * size.cy;
    for (size_t index = 0; index < cbytePlane; index++)
    {
        rgbytePlanar[index] = rgbyte[index * 3 + 0];
        rgbytePlanar[index + 1 * cbytePlane] = rgbyte[index * 3 + 1];
        rgbytePlanar[index + 2 * cbytePlane] = rgbyte[index * 3 + 2];
    }
    std::swap(rgbyte, rgbytePlanar);
}

bool VerifyEncodedBytes(const void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength)
{
    JlsParameters info = JlsParameters();
    auto error = JpegLsReadHeader(compressedData, compressedLength, &info, nullptr);
    if (error != ApiResult::OK)
        return false;

    std::vector<uint8_t> ourEncodedBytes(compressedLength + 16);
    size_t bytesWriten;
    error = JpegLsEncode(ourEncodedBytes.data(), ourEncodedBytes.size(), &bytesWriten, uncompressedData, uncompressedLength, &info, nullptr);
    if (error != ApiResult::OK)
        return false;

    for (size_t i = 0; i < compressedLength; ++i)
    {
        if (static_cast<const uint8_t*>(compressedData)[i] != ourEncodedBytes[i])
        {
            return false;
        }
    }

    return true;
}

void TestCompliance(const uint8_t* compressedBytes, size_t compressedLength, const uint8_t* rgbyteRaw, size_t cbyteRaw, bool bcheckEncode)
{
    JlsParameters info{};
    auto err = JpegLsReadHeader(compressedBytes, compressedLength, &info, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (bcheckEncode)
    {
        Assert::IsTrue(VerifyEncodedBytes(rgbyteRaw, cbyteRaw, compressedBytes, compressedLength));
    }

    std::vector<uint8_t> rgbyteOut(static_cast<size_t>(info.height) *info.width * ((info.bitsPerSample + 7) / 8) * info.components);

    err = JpegLsDecode(rgbyteOut.data(), rgbyteOut.size(), compressedBytes, compressedLength, nullptr, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (info.allowedLossyError == 0)
    {
        for (size_t i = 0; i < cbyteRaw; ++i)
        {
            if (rgbyteRaw[i] != rgbyteOut[i])
            {
                Assert::IsTrue(false);
                break;
            }
        }
    }
}

void DecompressFile(const char* strNameEncoded, const char* strNameRaw, int ioffs, bool bcheckEncode = true)
{
    std::cout << "Conformance test:" << strNameEncoded << "\n\r";
    std::vector<uint8_t> rgbyteFile;
    if (!ReadFile(strNameEncoded, &rgbyteFile))
        return;

    JlsParameters params{};
    if (JpegLsReadHeader(rgbyteFile.data(), rgbyteFile.size(), &params, nullptr) != ApiResult::OK)
    {
        Assert::IsTrue(false);
        return;
    }

    std::vector<uint8_t> rgbyteRaw;
    if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
        return;

    if (params.bitsPerSample > 8)
    {
        FixEndian(&rgbyteRaw, false);
    }

    if (params.interleaveMode == InterleaveMode::None && params.components == 3)
    {
        Triplet2Planar(rgbyteRaw, Size(params.width, params.height));
    }

    TestCompliance(rgbyteFile.data(), rgbyteFile.size(), rgbyteRaw.data(), rgbyteRaw.size(), bcheckEncode);
}

////uint8_t palettisedDataH10[] = {
////    0xFF, 0xD8, //Start of image (SOI) marker
////    0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker – marker segment follows
////    0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
////    0x02, //P = Precision = 2 bits per sample
////    0x00, 0x04, //Y = Number of lines = 4
////    0x00, 0x03, //X = Number of columns = 3
////    0x01, //Nf = Number of components in the frame = 1
////    0x01, //C1  = Component ID = 1 (first and only component)
////    0x11, //Sub-sampling: H1 = 1, V1 = 1
////    0x00, //Tq1 = 0 (this field is always 0)
////
////    0xFF, 0xF8, //LSE – JPEG-LS preset parameters marker
////    0x00, 0x11, //Length of marker segment = 17 bytes including the length field
////    0x02, //ID = 2, mapping table
////    0x05, //TID = 5 Table identifier (arbitrary)
////    0x03, //Wt = 3 Width of table entry
////    0xFF, 0xFF, 0xFF, //Entry for index 0
////    0xFF, 0x00, 0x00, //Entry for index 1
////    0x00, 0xFF, 0x00, //Entry for index 2
////    0x00, 0x00, 0xFF, //Entry for index 3
////
////    0xFF, 0xDA, //Start of scan (SOS) marker
////    0x00, 0x08, //Length of marker segment = 8 bytes including the length field
////    0x01, //Ns = Number of components for this scan = 1
////    0x01, //C1 = Component ID = 1
////    0x05, //Tm 1  = Mapping table identifier = 5
////    0x00, //NEAR = 0 (near-lossless max error)
////    0x00, //ILV = 0 (interleave mode = non-interleaved)
////    0x00, //Al = 0, Ah = 0 (no point transform)
////    0xDB, 0x95, 0xF0, //3 bytes of compressed image data
////    0xFF, 0xD9 //End of image (EOI) marker
////};

const std::array<uint8_t, 16> rgbyte = { 0,   0,  90,  74,
68,  50,  43, 205,
64, 145, 145, 145,
100, 145, 145, 145};
////const uint8_t rgbyteComp[] =   {   0xFF, 0xD8, 0xFF, 0xF7, 0x00, 0x0B, 0x08, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
////0xC0, 0x00, 0x00, 0x6C, 0x80, 0x20, 0x8E,
////0x01, 0xC0, 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x6E, 0xE6, 0x00, 0x00, 0x01, 0xBC, 0x18, 0x00,
////0x00, 0x05, 0xD8, 0x00, 0x00, 0x91, 0x60, 0xFF, 0xD9};

} // namespace

void TestSampleAnnexH3()
{
    ////Size size = Size(4,4);
    std::vector<uint8_t> vecRaw(16);
    memcpy(vecRaw.data(), rgbyte.data(), rgbyte.size());
    ////  TestJls(vecRaw, size, 8, 1, ILV_NONE, rgbyteComp, sizeof(rgbyteComp), false);
}

void TestColorTransforms_HpImages()
{
    DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP1.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP2.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP3.jls", "test/jlsimage/banny.ppm", 38, false);
}

void TestConformance()
{
    // Test 1
    DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 2
    DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 3
    DecompressFile("test/conformance/T8C2E0.JLS", "test/conformance/TEST8.PPM", 15);

    // Test 4
    DecompressFile("test/conformance/T8C0E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 5
    DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 6
    DecompressFile("test/conformance/T8C2E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 7
    // Test 8

    // Test 9
    DecompressFile("test/conformance/T8NDE0.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 10
    DecompressFile("test/conformance/T8NDE3.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 11
    DecompressFile("test/conformance/T16E0.JLS", "test/conformance/TEST16.PGM",16);

    // Test 12
    DecompressFile("test/conformance/T16E3.JLS", "test/conformance/TEST16.PGM",16);

    // additional, Lena compressed with other codec (UBC?), vfy with CharLS
    DecompressFile("test/lena8b.jls", "test/lena8b.raw",0);
}
<commit_msg>Remove not needed casts<commit_after>// Copyright (c) Team CharLS. All rights reserved. See the accompanying "LICENSE.md" for licensed use.

#include "compliance.h"
#include "util.h"

#include "../src/charls.h"

#include <iostream>
#include <vector>
#include <cstring>
#include <array>

using namespace charls;

namespace
{

void Triplet2Planar(std::vector<uint8_t>& rgbyte, Size size)
{
    std::vector<uint8_t> rgbytePlanar(rgbyte.size());

    const size_t cbytePlane = size.cx * size.cy;
    for (size_t index = 0; index < cbytePlane; index++)
    {
        rgbytePlanar[index] = rgbyte[index * 3 + 0];
        rgbytePlanar[index + 1 * cbytePlane] = rgbyte[index * 3 + 1];
        rgbytePlanar[index + 2 * cbytePlane] = rgbyte[index * 3 + 2];
    }
    std::swap(rgbyte, rgbytePlanar);
}

bool VerifyEncodedBytes(const void* uncompressedData, size_t uncompressedLength, const void* compressedData, size_t compressedLength)
{
    JlsParameters info = JlsParameters();
    auto error = JpegLsReadHeader(compressedData, compressedLength, &info, nullptr);
    if (error != ApiResult::OK)
        return false;

    std::vector<uint8_t> ourEncodedBytes(compressedLength + 16);
    size_t bytesWriten;
    error = JpegLsEncode(ourEncodedBytes.data(), ourEncodedBytes.size(), &bytesWriten, uncompressedData, uncompressedLength, &info, nullptr);
    if (error != ApiResult::OK)
        return false;

    for (size_t i = 0; i < compressedLength; ++i)
    {
        if (static_cast<const uint8_t*>(compressedData)[i] != ourEncodedBytes[i])
        {
            return false;
        }
    }

    return true;
}

void TestCompliance(const uint8_t* compressedBytes, size_t compressedLength, const uint8_t* rgbyteRaw, size_t cbyteRaw, bool bcheckEncode)
{
    JlsParameters info{};
    auto err = JpegLsReadHeader(compressedBytes, compressedLength, &info, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (bcheckEncode)
    {
        Assert::IsTrue(VerifyEncodedBytes(rgbyteRaw, cbyteRaw, compressedBytes, compressedLength));
    }

    std::vector<uint8_t> rgbyteOut(static_cast<size_t>(info.height) *info.width * ((info.bitsPerSample + 7) / 8) * info.components);

    err = JpegLsDecode(rgbyteOut.data(), rgbyteOut.size(), compressedBytes, compressedLength, nullptr, nullptr);
    Assert::IsTrue(err == ApiResult::OK);

    if (info.allowedLossyError == 0)
    {
        for (size_t i = 0; i < cbyteRaw; ++i)
        {
            if (rgbyteRaw[i] != rgbyteOut[i])
            {
                Assert::IsTrue(false);
                break;
            }
        }
    }
}

void DecompressFile(const char* strNameEncoded, const char* strNameRaw, int ioffs, bool bcheckEncode = true)
{
    std::cout << "Conformance test:" << strNameEncoded << "\n\r";
    std::vector<uint8_t> rgbyteFile;
    if (!ReadFile(strNameEncoded, &rgbyteFile))
        return;

    JlsParameters params{};
    if (JpegLsReadHeader(rgbyteFile.data(), rgbyteFile.size(), &params, nullptr) != ApiResult::OK)
    {
        Assert::IsTrue(false);
        return;
    }

    std::vector<uint8_t> rgbyteRaw;
    if (!ReadFile(strNameRaw, &rgbyteRaw, ioffs))
        return;

    if (params.bitsPerSample > 8)
    {
        FixEndian(&rgbyteRaw, false);
    }

    if (params.interleaveMode == InterleaveMode::None && params.components == 3)
    {
        Triplet2Planar(rgbyteRaw, Size(params.width, params.height));
    }

    TestCompliance(rgbyteFile.data(), rgbyteFile.size(), rgbyteRaw.data(), rgbyteRaw.size(), bcheckEncode);
}

////uint8_t palettisedDataH10[] = {
////    0xFF, 0xD8, //Start of image (SOI) marker
////    0xFF, 0xF7, //Start of JPEG-LS frame (SOF 55) marker – marker segment follows
////    0x00, 0x0B, //Length of marker segment = 11 bytes including the length field
////    0x02, //P = Precision = 2 bits per sample
////    0x00, 0x04, //Y = Number of lines = 4
////    0x00, 0x03, //X = Number of columns = 3
////    0x01, //Nf = Number of components in the frame = 1
////    0x01, //C1  = Component ID = 1 (first and only component)
////    0x11, //Sub-sampling: H1 = 1, V1 = 1
////    0x00, //Tq1 = 0 (this field is always 0)
////
////    0xFF, 0xF8, //LSE – JPEG-LS preset parameters marker
////    0x00, 0x11, //Length of marker segment = 17 bytes including the length field
////    0x02, //ID = 2, mapping table
////    0x05, //TID = 5 Table identifier (arbitrary)
////    0x03, //Wt = 3 Width of table entry
////    0xFF, 0xFF, 0xFF, //Entry for index 0
////    0xFF, 0x00, 0x00, //Entry for index 1
////    0x00, 0xFF, 0x00, //Entry for index 2
////    0x00, 0x00, 0xFF, //Entry for index 3
////
////    0xFF, 0xDA, //Start of scan (SOS) marker
////    0x00, 0x08, //Length of marker segment = 8 bytes including the length field
////    0x01, //Ns = Number of components for this scan = 1
////    0x01, //C1 = Component ID = 1
////    0x05, //Tm 1  = Mapping table identifier = 5
////    0x00, //NEAR = 0 (near-lossless max error)
////    0x00, //ILV = 0 (interleave mode = non-interleaved)
////    0x00, //Al = 0, Ah = 0 (no point transform)
////    0xDB, 0x95, 0xF0, //3 bytes of compressed image data
////    0xFF, 0xD9 //End of image (EOI) marker
////};

const std::array<uint8_t, 16> rgbyte = { 0,   0,  90,  74,
68,  50,  43, 205,
64, 145, 145, 145,
100, 145, 145, 145};
////const uint8_t rgbyteComp[] =   {   0xFF, 0xD8, 0xFF, 0xF7, 0x00, 0x0B, 0x08, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
////0xC0, 0x00, 0x00, 0x6C, 0x80, 0x20, 0x8E,
////0x01, 0xC0, 0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x6E, 0xE6, 0x00, 0x00, 0x01, 0xBC, 0x18, 0x00,
////0x00, 0x05, 0xD8, 0x00, 0x00, 0x91, 0x60, 0xFF, 0xD9};

} // namespace

void TestSampleAnnexH3()
{
    ////Size size = Size(4,4);
    std::vector<uint8_t> vecRaw(16);
    memcpy(vecRaw.data(), rgbyte.data(), rgbyte.size());
    ////  TestJls(vecRaw, size, 8, 1, ILV_NONE, rgbyteComp, sizeof(rgbyteComp), false);
}

void TestColorTransforms_HpImages()
{
    DecompressFile("test/jlsimage/banny_normal.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP1.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP2.jls", "test/jlsimage/banny.ppm", 38, false);
    DecompressFile("test/jlsimage/banny_HP3.jls", "test/jlsimage/banny.ppm", 38, false);
}

void TestConformance()
{
    // Test 1
    DecompressFile("test/conformance/T8C0E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 2
    DecompressFile("test/conformance/T8C1E0.JLS", "test/conformance/TEST8.PPM",15);

    // Test 3
    DecompressFile("test/conformance/T8C2E0.JLS", "test/conformance/TEST8.PPM", 15);

    // Test 4
    DecompressFile("test/conformance/T8C0E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 5
    DecompressFile("test/conformance/T8C1E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 6
    DecompressFile("test/conformance/T8C2E3.JLS", "test/conformance/TEST8.PPM",15);

    // Test 7
    // Test 8

    // Test 9
    DecompressFile("test/conformance/T8NDE0.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 10
    DecompressFile("test/conformance/T8NDE3.JLS", "test/conformance/TEST8BS2.PGM",15);

    // Test 11
    DecompressFile("test/conformance/T16E0.JLS", "test/conformance/TEST16.PGM",16);

    // Test 12
    DecompressFile("test/conformance/T16E3.JLS", "test/conformance/TEST16.PGM",16);

    // additional, Lena compressed with other codec (UBC?), vfy with CharLS
    DecompressFile("test/lena8b.jls", "test/lena8b.raw",0);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>

#include <TAlienCollection.h>
#include <TFile.h>
#include <TGrid.h>
#include <TGridResult.h>
#include <TMath.h>
#include <TROOT.h>
#include <TString.h>
#include <TSystem.h>

#include "AliCDBManager.h"
#include "AliLog.h"
#include "AliQA.h"
#include "AliQADataMakerSteer.h"
#include "AliRawReader.h"
#include "AliRawReaderRoot.h"
#include "AliDAQ.h"

TString ClassName() { return "rawqa" ; }

//________________________________qa______________________________________
void rawqa(const Int_t runNumber, Int_t maxFiles = 10, const char* year = "08")
{
	const char * kDefaultOCDBStorage = Form("alien://folder=/alice/data/20%s/LHC%sa/OCDB/", year, year) ;

	UInt_t maxEvents = 99999 ;
	if ( maxFiles < 0 ) {
		maxEvents = TMath::Abs(maxFiles) ;
		maxFiles = 99 ;
	}
	AliLog::SetGlobalDebugLevel(0) ;
	// connect to the grid
	TGrid * grid = 0x0 ;
       	grid = TGrid::Connect("alien://") ;

	Bool_t detIn[AliDAQ::kNDetectors] = {kFALSE} ;
	char * detNameOff[AliDAQ::kNDetectors] = {"ITS", "ITS", "ITS", "TPC", "TRD", "TOF", "HMPID", "PHOS", "PHOS", "PMD", "MUON", "MUON", "FMD", "T0", "VZERO", "ZDC", "ACORDE", "TRG", "EMCAL", "DAQ_TEST", "HLT"} ;
	// make the file name pattern year and run number
	TString pattern;
	pattern.Form("%9d",runNumber);
	pattern.ReplaceAll(" ", "0") ;
	pattern.Prepend(year);
	pattern.Append("*0.root");

	// find the files associated to this run
	TGridResult * result = 0x0 ;
	Bool_t local = kFALSE ;
	if (grid) { // get the list of files from AliEn directly
	  TString baseDir;
	  baseDir.Form("/alice/data/20%s/",year);
	  result = grid->Query(baseDir, pattern) ;
	} else {
	  TString collectionFile(pattern) ;
	  collectionFile.Append(".xml") ;
	  if ( gSystem->AccessPathName(collectionFile) == 0 ) { // get the list of files from an a-priori created collection file
	    TAlienCollection collection(collectionFile.Data(), maxFiles) ;
	    result = collection.GetGridResult("", 0, 0);
	  } else { // get the list of files from the local current directory
	    local = kTRUE ;
	    char line[100] ;
	    sprintf(line, ".! ls %s*.root > tempo.txt", pattern.Data()) ;
	    gROOT->ProcessLine(line) ;
	  }
	}
	AliLog::Flush();
	ifstream in ;
	if (local)
		in.open("tempo.txt", ifstream::in) ;

	AliCDBManager* man = AliCDBManager::Instance();
	man->SetDefaultStorage(kDefaultOCDBStorage) ;
	AliQA::SetQARefStorage(Form("%s%s/", AliQA::GetQARefDefaultStorage(), year)) ;
	man->SetSpecificStorage("*", AliQA::GetQARefStorage());
	AliQADataMakerSteer qas ;
	TString detectors  = "";
	TString detectorsW = "";
	UShort_t file = 0 ;
	UShort_t filesProcessed = 0 ;
	UShort_t eventsProcessed = 0 ;
	for ( file = 0 ; file < maxFiles ; file++) {
		if ( qas.GetCurrentEvent() >= maxEvents)
			break ;

		TString fileName ;
		if ( local) {
			in >> fileName ;
		}
		else
			fileName = result->GetKey(file, "turl");
	       	if ( fileName == "" )
		        break ;
		if ( fileName.Contains("tag") )
			continue;
                filesProcessed++ ;
		char input[200] ;
		if (local)
			sprintf(input, "%s", fileName.Data()) ;
		else
			sprintf(input, "%s", result->GetKey(file, "turl"));
		AliInfo(Form("Proccessing file # %d --> %s", file, input)) ;
		AliLog::Flush();
		// check which detectors are present
		AliRawReader * rawReader = new AliRawReaderRoot(input);
		while ( rawReader->NextEvent() ) {
			man->SetRun(rawReader->GetRunNumber());
			AliLog::Flush();
			UChar_t * data ;
			while (rawReader->ReadNextData(data)) {
				Int_t detID = rawReader->GetDetectorID();
				if (detID < 0 || detID >= AliDAQ::kNDetectors) {
					AliError("Wrong detector ID! Skipping payload...");
					continue;
				}
				detIn[detID] = kTRUE ;
			}
			for (Int_t detID = 0; detID < AliDAQ::kNDetectors ; detID++) {
				if (detIn[detID]) {
					if ( ! detectors.Contains(detNameOff[detID]) ) {
						detectors.Append(detNameOff[detID]) ;
						detectors.Append(" ") ;
					}
				}
			}
			if ( !detectors.IsNull() )
				break ;
		}
		// TEMPORARY REMOVAL OF TRD!!!
		detectors.ReplaceAll("TRD", "") ;
		// TEMPORARY REMOVAL OF TRD!!!
		if ( !detectors.IsNull() ) {
			qas.SetMaxEvents(maxEvents) ;
			detectorsW = qas.Run(detectors, rawReader) ;
			qas.Reset() ;
		} else {
			AliError("No valid detectors found") ;
		}
		delete rawReader ;
		eventsProcessed += qas.GetCurrentEvent() ;
	}
	AliLog::Flush();
	qas.Merge(runNumber) ;

	AliLog::Flush();
	// The summary
	AliInfo(Form("\n\n********** Summary for run %d **********", runNumber)) ;
	printf("     detectors present in the run        : %s\n", detectors.Data()) ;
	printf("     detectors present in the run with QA: %s\n", detectorsW.Data()) ;
	printf("     number of files/events processed    : %d/%d\n", filesProcessed, eventsProcessed) ;
	TFile * qaResult = TFile::Open(AliQA::GetQAResultFileName()) ;
	if ( qaResult ) {
		AliQA * qa = dynamic_cast<AliQA *>(qaResult->Get("QA")) ;
		for (Int_t index = 0 ; index < AliQA::kNDET ; index++)
			if (detectorsW.Contains(AliQA::GetDetName(AliQA::DETECTORINDEX(index))))
				qa->ShowStatus(AliQA::DETECTORINDEX(index)) ;
	} else {
		AliError(Form("%s has not been produced !", AliQA::GetQAResultFileName())) ;
	}
}
<commit_msg>added TRD back<commit_after>#include <iostream>
#include <fstream>

#include <TAlienCollection.h>
#include <TFile.h>
#include <TGrid.h>
#include <TGridResult.h>
#include <TMath.h>
#include <TROOT.h>
#include <TString.h>
#include <TSystem.h>

#include "AliCDBManager.h"
#include "AliDAQ.h"
#include "AliLog.h"
#include "AliQA.h"
#include "AliQADataMakerSteer.h"
#include "AliRawReader.h"
#include "AliRawReaderRoot.h"
#include "AliTRDrawStreamBase.h"

TString ClassName() { return "rawqa" ; }

//________________________________qa______________________________________
void rawqa(const Int_t runNumber, Int_t maxFiles = 10, const char* year = "08")
{
	const char * kDefaultOCDBStorage = Form("alien://folder=/alice/data/20%s/LHC%sa/OCDB/", year, year) ;

	UInt_t maxEvents = 99999 ;
	if ( maxFiles < 0 ) {
		maxEvents = TMath::Abs(maxFiles) ;
		maxFiles = 99 ;
	}
	AliLog::SetGlobalDebugLevel(0) ;
	// connect to the grid
	TGrid * grid = 0x0 ;
       	grid = TGrid::Connect("alien://") ;

	Bool_t detIn[AliDAQ::kNDetectors] = {kFALSE} ;
	char * detNameOff[AliDAQ::kNDetectors] = {"ITS", "ITS", "ITS", "TPC", "TRD", "TOF", "HMPID", "PHOS", "PHOS", "PMD", "MUON", "MUON", "FMD", "T0", "VZERO", "ZDC", "ACORDE", "TRG", "EMCAL", "DAQ_TEST", "HLT"} ;
	// make the file name pattern year and run number
	TString pattern;
	pattern.Form("%9d",runNumber);
	pattern.ReplaceAll(" ", "0") ;
	pattern.Prepend(year);
	pattern.Append("*0.root");

	// find the files associated to this run
	TGridResult * result = 0x0 ;
	Bool_t local = kFALSE ;
	if (grid) { // get the list of files from AliEn directly
	  TString baseDir;
	  baseDir.Form("/alice/data/20%s/",year);
	  result = grid->Query(baseDir, pattern) ;
	} else {
	  TString collectionFile(pattern) ;
	  collectionFile.Append(".xml") ;
	  if ( gSystem->AccessPathName(collectionFile) == 0 ) { // get the list of files from an a-priori created collection file
	    TAlienCollection collection(collectionFile.Data(), maxFiles) ;
	    result = collection.GetGridResult("", 0, 0);
	  } else { // get the list of files from the local current directory
	    local = kTRUE ;
	    char line[100] ;
	    sprintf(line, ".! ls %s*.root > tempo.txt", pattern.Data()) ;
	    gROOT->ProcessLine(line) ;
	  }
	}
	AliLog::Flush();
	ifstream in ;
	if (local)
		in.open("tempo.txt", ifstream::in) ;

	AliCDBManager* man = AliCDBManager::Instance();
	man->SetDefaultStorage(kDefaultOCDBStorage) ;
	AliQA::SetQARefStorage(Form("%s%s/", AliQA::GetQARefDefaultStorage(), year)) ;
	man->SetSpecificStorage("*", AliQA::GetQARefStorage());
	AliQADataMakerSteer qas ;
	TString detectors  = "";
	TString detectorsW = "";
	UShort_t file = 0 ;
	UShort_t filesProcessed = 0 ;
	UShort_t eventsProcessed = 0 ;
	for ( file = 0 ; file < maxFiles ; file++) {
		if ( qas.GetCurrentEvent() >= maxEvents)
			break ;

		TString fileName ;
		if ( local) {
			in >> fileName ;
		}
		else
			fileName = result->GetKey(file, "turl");
	       	if ( fileName == "" )
		        break ;
		if ( fileName.Contains("tag") )
			continue;
                filesProcessed++ ;
		char input[200] ;
		if (local)
			sprintf(input, "%s", fileName.Data()) ;
		else
			sprintf(input, "%s", result->GetKey(file, "turl"));
		AliInfo(Form("Proccessing file # %d --> %s", file, input)) ;
		AliLog::Flush();
		// check which detectors are present
		AliRawReader * rawReader = new AliRawReaderRoot(input);
		AliTRDrawStreamBase::SetRawStreamVersion("TB");
		while ( rawReader->NextEvent() ) {
			man->SetRun(rawReader->GetRunNumber());
			AliLog::Flush();
			UChar_t * data ;
			while (rawReader->ReadNextData(data)) {
				Int_t detID = rawReader->GetDetectorID();
				if (detID < 0 || detID >= AliDAQ::kNDetectors) {
					AliError("Wrong detector ID! Skipping payload...");
					continue;
				}
				detIn[detID] = kTRUE ;
			}
			for (Int_t detID = 0; detID < AliDAQ::kNDetectors ; detID++) {
				if (detIn[detID]) {
					if ( ! detectors.Contains(detNameOff[detID]) ) {
						detectors.Append(detNameOff[detID]) ;
						detectors.Append(" ") ;
					}
				}
			}
			if ( !detectors.IsNull() )
				break ;
		}
		if ( !detectors.IsNull() ) {
			qas.SetMaxEvents(maxEvents) ;
			detectorsW = qas.Run(detectors, rawReader) ;
			qas.Reset() ;
		} else {
			AliError("No valid detectors found") ;
		}
		delete rawReader ;
		eventsProcessed += qas.GetCurrentEvent() ;
	}
	AliLog::Flush();
	qas.Merge(runNumber) ;

	AliLog::Flush();
	// The summary
	AliInfo(Form("\n\n********** Summary for run %d **********", runNumber)) ;
	printf("     detectors present in the run        : %s\n", detectors.Data()) ;
	printf("     detectors present in the run with QA: %s\n", detectorsW.Data()) ;
	printf("     number of files/events processed    : %d/%d\n", filesProcessed, eventsProcessed) ;
	TFile * qaResult = TFile::Open(AliQA::GetQAResultFileName()) ;
	if ( qaResult ) {
		AliQA * qa = dynamic_cast<AliQA *>(qaResult->Get("QA")) ;
		for (Int_t index = 0 ; index < AliQA::kNDET ; index++)
			if (detectorsW.Contains(AliQA::GetDetName(AliQA::DETECTORINDEX(index))))
				qa->ShowStatus(AliQA::DETECTORINDEX(index)) ;
	} else {
		AliError(Form("%s has not been produced !", AliQA::GetQAResultFileName())) ;
	}
}
<|endoftext|>


<commit_before>#include <stan/math/prim.hpp>
#include <test/unit/math/prim/prob/vector_rng_test_helper.hpp>
#include <test/unit/math/prim/prob/NegativeBinomial2LogTestRig.hpp>
#include <gtest/gtest.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/math/distributions.hpp>
#include <algorithm>
#include <limits>
#include <vector>
#include <string>

TEST(ProbDistributionsNegativeBinomial2Log, errorCheck) {
  check_dist_throws_all_types(NegativeBinomial2LogTestRig());
}

TEST(ProbDistributionsNegBinomial2Log, error_check) {
  using std::log;

  boost::random::mt19937 rng;
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(6, 2, rng));
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(-0.5, 1, rng));
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(log(1e8), 1, rng));

  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(0, -2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(6, -2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(-6, -0.1, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   stan::math::positive_infinity(), 2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   stan::math::positive_infinity(), 6, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   2, stan::math::positive_infinity(), rng),
               std::domain_error);

  std::string error_msg;

  error_msg
      = "neg_binomial_2_log_rng: Exponential "
        "of the log-location parameter divided by the precision "
        "parameter is inf, but must be finite!";
  try {
    stan::math::neg_binomial_2_log_rng(log(1e300), 1e-300, rng);
    FAIL() << "neg_binomial_2_log_rng should have thrown" << std::endl;
  } catch (const std::exception& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos)
      FAIL() << "Error message is different than expected" << std::endl
             << "EXPECTED: " << error_msg << std::endl
             << "FOUND: " << e.what() << std::endl;
    SUCCEED();
  }

  error_msg
      = "neg_binomial_2_log_rng: Random number that "
        "came from gamma distribution is";
  try {
    stan::math::neg_binomial_2_log_rng(log(1e10), 1e20, rng);
    FAIL() << "neg_binomial_2_log_rng should have thrown" << std::endl;
  } catch (const std::exception& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos)
      FAIL() << "Error message is different than expected" << std::endl
             << "EXPECTED: " << error_msg << std::endl
             << "FOUND: " << e.what() << std::endl;
    SUCCEED();
  }
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(1.1,
                                                     1.1 / (1.1 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 1.1, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest2) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(0.6,
                                                     0.6 / (0.6 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 0.6, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest3) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(121,
                                                     121 / (121 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 121, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbNegBinomial2, log_matches_lpmf) {
  double y = 0.8;
  double mu = 1.1;
  double phi = 2.3;

  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf(y, mu, phi)),
                  (stan::math::neg_binomial_2_log(y, mu, phi)));
  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf<true>(y, mu, phi)),
                  (stan::math::neg_binomial_2_log<true>(y, mu, phi)));
  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf<false>(y, mu, phi)),
                  (stan::math::neg_binomial_2_log<false>(y, mu, phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<true, double, double, double>(y, mu,
                                                                     phi)),
      (stan::math::neg_binomial_2_log<true, double, double, double>(y, mu,
                                                                    phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<false, double, double, double>(y, mu,
                                                                      phi)),
      (stan::math::neg_binomial_2_log<false, double, double, double>(y, mu,
                                                                     phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<double, double, double>(y, mu, phi)),
      (stan::math::neg_binomial_2_log<double, double, double>(y, mu, phi)));
}

TEST(ProbDistributionsNegBinomial2Log, neg_binomial_2_log_grid_test) {
  std::vector<double> mu_log_to_test
      = {-101, -27, -3, -1, -0.132, 0, 4, 10, 87};
  std::vector<double> phi_to_test = {2e-5, 0.36, 1, 2.3e5, 1.8e10, 6e16};
  std::vector<int> n_to_test = {0, 1, 10, 39, 101, 3048, 150054};

  // TODO(martinmdorak) Only weak tolerance for this quick fix
  auto tolerance = [](double x) { return std::max(fabs(x * 1e-8), 1e-8); };

  for (double mu_log : mu_log_to_test) {
    for (double phi : phi_to_test) {
      for (int n : n_to_test) {
        double val_log = stan::math::neg_binomial_2_log_lpmf(n, mu_log, phi);
        EXPECT_LE(val_log, 0)
            << "neg_binomial_2_log_lpmf yields " << val_log
            << " which si greater than 0 for n = " << n
            << ", mu_log = " << mu_log << ", phi = " << phi << ".";
        double val_orig
            = stan::math::neg_binomial_2_lpmf(n, std::exp(mu_log), phi);
        EXPECT_NEAR(val_log, val_orig, tolerance(val_orig))
            << "neg_binomial_2_log_lpmf yields different result (" << val_log
            << ") than neg_binomial_2_lpmf (" << val_orig << ") for n = " << n
            << ", mu_log = " << mu_log << ", phi = " << phi << ".";
      }
    }
  }
}
<commit_msg>Reducing the scope of neg_binomial_2_log_lpmf tests<commit_after>#include <stan/math/prim.hpp>
#include <test/unit/math/prim/prob/vector_rng_test_helper.hpp>
#include <test/unit/math/prim/prob/NegativeBinomial2LogTestRig.hpp>
#include <gtest/gtest.h>
#include <boost/random/mersenne_twister.hpp>
#include <boost/math/distributions.hpp>
#include <algorithm>
#include <limits>
#include <vector>
#include <string>

TEST(ProbDistributionsNegativeBinomial2Log, errorCheck) {
  check_dist_throws_all_types(NegativeBinomial2LogTestRig());
}

TEST(ProbDistributionsNegBinomial2Log, error_check) {
  using std::log;

  boost::random::mt19937 rng;
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(6, 2, rng));
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(-0.5, 1, rng));
  EXPECT_NO_THROW(stan::math::neg_binomial_2_log_rng(log(1e8), 1, rng));

  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(0, -2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(6, -2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(-6, -0.1, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   stan::math::positive_infinity(), 2, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   stan::math::positive_infinity(), 6, rng),
               std::domain_error);
  EXPECT_THROW(stan::math::neg_binomial_2_log_rng(
                   2, stan::math::positive_infinity(), rng),
               std::domain_error);

  std::string error_msg;

  error_msg
      = "neg_binomial_2_log_rng: Exponential "
        "of the log-location parameter divided by the precision "
        "parameter is inf, but must be finite!";
  try {
    stan::math::neg_binomial_2_log_rng(log(1e300), 1e-300, rng);
    FAIL() << "neg_binomial_2_log_rng should have thrown" << std::endl;
  } catch (const std::exception& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos)
      FAIL() << "Error message is different than expected" << std::endl
             << "EXPECTED: " << error_msg << std::endl
             << "FOUND: " << e.what() << std::endl;
    SUCCEED();
  }

  error_msg
      = "neg_binomial_2_log_rng: Random number that "
        "came from gamma distribution is";
  try {
    stan::math::neg_binomial_2_log_rng(log(1e10), 1e20, rng);
    FAIL() << "neg_binomial_2_log_rng should have thrown" << std::endl;
  } catch (const std::exception& e) {
    if (std::string(e.what()).find(error_msg) == std::string::npos)
      FAIL() << "Error message is different than expected" << std::endl
             << "EXPECTED: " << error_msg << std::endl
             << "FOUND: " << e.what() << std::endl;
    SUCCEED();
  }
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(1.1,
                                                     1.1 / (1.1 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 1.1, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest2) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(0.6,
                                                     0.6 / (0.6 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 0.6, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbDistributionsNegBinomial2Log, chiSquareGoodnessFitTest3) {
  boost::random::mt19937 rng;
  int N = 1000;
  int K = stan::math::round(2 * std::pow(N, 0.4));
  boost::math::negative_binomial_distribution<> dist(121,
                                                     121 / (121 + exp(2.4)));
  boost::math::chi_squared mydist(K - 1);

  int loc[K - 1];
  for (int i = 1; i < K; i++)
    loc[i - 1] = i - 1;

  int count = 0;
  double bin[K];
  double expect[K];
  for (int i = 0; i < K; i++) {
    bin[i] = 0;
    expect[i] = N * pdf(dist, i);
  }
  expect[K - 1] = N * (1 - cdf(dist, K - 1));

  while (count < N) {
    int a = stan::math::neg_binomial_2_log_rng(2.4, 121, rng);
    int i = 0;
    while (i < K - 1 && a > loc[i])
      ++i;
    ++bin[i];
    count++;
  }

  double chi = 0;

  for (int j = 0; j < K; j++)
    chi += ((bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]);

  EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6)));
}

TEST(ProbNegBinomial2, log_matches_lpmf) {
  double y = 0.8;
  double mu = 1.1;
  double phi = 2.3;

  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf(y, mu, phi)),
                  (stan::math::neg_binomial_2_log(y, mu, phi)));
  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf<true>(y, mu, phi)),
                  (stan::math::neg_binomial_2_log<true>(y, mu, phi)));
  EXPECT_FLOAT_EQ((stan::math::neg_binomial_2_lpmf<false>(y, mu, phi)),
                  (stan::math::neg_binomial_2_log<false>(y, mu, phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<true, double, double, double>(y, mu,
                                                                     phi)),
      (stan::math::neg_binomial_2_log<true, double, double, double>(y, mu,
                                                                    phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<false, double, double, double>(y, mu,
                                                                      phi)),
      (stan::math::neg_binomial_2_log<false, double, double, double>(y, mu,
                                                                     phi)));
  EXPECT_FLOAT_EQ(
      (stan::math::neg_binomial_2_lpmf<double, double, double>(y, mu, phi)),
      (stan::math::neg_binomial_2_log<double, double, double>(y, mu, phi)));
}

TEST(ProbDistributionsNegBinomial2Log, neg_binomial_2_log_grid_test) {
  std::vector<double> mu_log_to_test
      = {-101, -27, -3, -1, -0.132, 0, 4, 10, 87};
  // TODO(martinmodrak) Reducing the span of the test, should be fixed
  // along with #1495
  // std::vector<double> phi_to_test = {2e-5, 0.36, 1, 10, 2.3e5, 1.8e10, 6e16};
  std::vector<double> phi_to_test = {0.36, 1, 10};
  std::vector<int> n_to_test = {0, 1, 10, 39, 101, 3048, 150054};

  // TODO(martinmdorak) Only weak tolerance for this quick fix
  auto tolerance = [](double x) { return std::max(fabs(x * 1e-8), 1e-8); };

  for (double mu_log : mu_log_to_test) {
    for (double phi : phi_to_test) {
      for (int n : n_to_test) {
        double val_log = stan::math::neg_binomial_2_log_lpmf(n, mu_log, phi);
        EXPECT_LE(val_log, 0)
            << "neg_binomial_2_log_lpmf yields " << val_log
            << " which si greater than 0 for n = " << n
            << ", mu_log = " << mu_log << ", phi = " << phi << ".";
        double val_orig
            = stan::math::neg_binomial_2_lpmf(n, std::exp(mu_log), phi);
        EXPECT_NEAR(val_log, val_orig, tolerance(val_orig))
            << "neg_binomial_2_log_lpmf yields different result (" << val_log
            << ") than neg_binomial_2_lpmf (" << val_orig << ") for n = " << n
            << ", mu_log = " << mu_log << ", phi = " << phi << ".";
      }
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_shutdown.h"

#include <map>
#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "build/build_config.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/switch_utils.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_WIN)
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
#include "chrome/browser/rlz/rlz.h"
#endif

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#endif

using base::Time;
using base::TimeDelta;
using content::BrowserThread;

namespace browser_shutdown {

// Whether the browser is trying to quit (e.g., Quit chosen from menu).
bool g_trying_to_quit = false;

// Whether the browser should quit without closing browsers.
bool g_shutting_down_without_closing_browsers = false;

Time shutdown_started_;
ShutdownType shutdown_type_ = NOT_VALID;
int shutdown_num_processes_;
int shutdown_num_processes_slow_;

bool delete_resources_on_shutdown = true;

const char kShutdownMsFile[] = "chrome_shutdown_ms.txt";

void RegisterPrefs(PrefService* local_state) {
  local_state->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0);
}

ShutdownType GetShutdownType() {
  return shutdown_type_;
}

void OnShutdownStarting(ShutdownType type) {
  if (shutdown_type_ != NOT_VALID)
    return;

  shutdown_type_ = type;
  // For now, we're only counting the number of renderer processes
  // since we can't safely count the number of plugin processes from this
  // thread, and we'd really like to avoid anything which might add further
  // delays to shutdown time.
  shutdown_started_ = Time::Now();

  // Call FastShutdown on all of the RenderProcessHosts.  This will be
  // a no-op in some cases, so we still need to go through the normal
  // shutdown path for the ones that didn't exit here.
  shutdown_num_processes_ = 0;
  shutdown_num_processes_slow_ = 0;
  for (content::RenderProcessHost::iterator i(
          content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    ++shutdown_num_processes_;
    if (!i.GetCurrentValue()->FastShutdownIfPossible())
      ++shutdown_num_processes_slow_;
  }
}

FilePath GetShutdownMsPath() {
  FilePath shutdown_ms_file;
  PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file);
  return shutdown_ms_file.AppendASCII(kShutdownMsFile);
}

bool ShutdownPreThreadsStop() {
#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
      "BrowserShutdownStarted", false);
#endif
  // During shutdown we will end up some blocking operations.  But the
  // work needs to get done and we're going to wait for them no matter
  // what thread they're on, so don't worry about it slowing down
  // shutdown.
  base::ThreadRestrictions::SetIOAllowed(true);

  // Shutdown the IPC channel to the service processes.
  ServiceProcessControl::GetInstance()->Disconnect();

  // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough
  // time to get here. If you have something that *must* happen on end session,
  // consider putting it in BrowserProcessImpl::EndSession.
  PrefService* prefs = g_browser_process->local_state();

  MetricsService* metrics = g_browser_process->metrics_service();
  if (metrics)
    metrics->RecordCompletedSessionEnd();

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Record the shutdown info so that we can put it into a histogram at next
    // startup.
    prefs->SetInteger(prefs::kShutdownType, shutdown_type_);
    prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_);
    prefs->SetInteger(prefs::kShutdownNumProcessesSlow,
                      shutdown_num_processes_slow_);
  }

  // Check local state for the restart flag so we can restart the session below.
  bool restart_last_session = false;
  if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) {
    restart_last_session =
        prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown);
    prefs->ClearPref(prefs::kRestartLastSessionOnShutdown);
  }

  prefs->CommitPendingWrite();

#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
  // Cleanup any statics created by RLZ. Must be done before NotificationService
  // is destroyed.
  RLZTracker::CleanupRlz();
#endif

  return restart_last_session;
}

void ShutdownPostThreadsStop(bool restart_last_session) {
  // The jank'o'meter requires that the browser process has been destroyed
  // before calling UninstallJankometer().
  delete g_browser_process;
  g_browser_process = NULL;

  // crbug.com/95079 - This needs to happen after the browser process object
  // goes away.
  ProfileManager::NukeDeletedProfilesFromDisk();

#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("BrowserDeleted",
                                                        true);
#endif

  // Uninstall Jank-O-Meter here after the IO thread is no longer running.
  UninstallJankometer();

  if (delete_resources_on_shutdown)
    ResourceBundle::CleanupSharedInstance();

#if defined(OS_WIN)
  if (!browser_util::IsBrowserAlreadyRunning() &&
      shutdown_type_ != browser_shutdown::END_SESSION) {
    upgrade_util::SwapNewChromeExeIfPresent();
  }
#endif

  if (restart_last_session) {
#if !defined(OS_CHROMEOS)
    // Make sure to relaunch the browser with the original command line plus
    // the Restore Last Session flag. Note that Chrome can be launched (ie.
    // through ShellExecute on Windows) with a switch argument terminator at
    // the end (double dash, as described in b/1366444) plus a URL,
    // which prevents us from appending to the command line directly (issue
    // 46182). We therefore use GetSwitches to copy the command line (it stops
    // at the switch argument terminator).
    CommandLine old_cl(*CommandLine::ForCurrentProcess());
    scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram()));
    std::map<std::string, CommandLine::StringType> switches =
        old_cl.GetSwitches();
    // Remove the switches that shouldn't persist across restart.
    about_flags::RemoveFlagsSwitches(&switches);
    switches::RemoveSwitchesForAutostart(&switches);
    // Append the old switches to the new command line.
    for (std::map<std::string, CommandLine::StringType>::const_iterator i =
        switches.begin(); i != switches.end(); ++i) {
      CommandLine::StringType switch_value = i->second;
      if (!switch_value.empty())
        new_cl->AppendSwitchNative(i->first, i->second);
      else
        new_cl->AppendSwitch(i->first);
    }
    upgrade_util::RelaunchChromeBrowser(*new_cl.get());
#else
    NOTIMPLEMENTED();
#endif  // !defined(OS_CHROMEOS)
  }

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Measure total shutdown time as late in the process as possible
    // and then write it to a file to be read at startup.
    // We can't use prefs since all services are shutdown at this point.
    TimeDelta shutdown_delta = Time::Now() - shutdown_started_;
    std::string shutdown_ms =
        base::Int64ToString(shutdown_delta.InMilliseconds());
    int len = static_cast<int>(shutdown_ms.length()) + 1;
    FilePath shutdown_ms_file = GetShutdownMsPath();
    file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
  }

#if defined(OS_CHROMEOS)
  BrowserList::NotifyAndTerminate(false);
#endif

  ChromeURLDataManager::DeleteDataSources();
}

void ReadLastShutdownFile(
    ShutdownType type,
    int num_procs,
    int num_procs_slow) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  FilePath shutdown_ms_file = GetShutdownMsPath();
  std::string shutdown_ms_str;
  int64 shutdown_ms = 0;
  if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str))
    base::StringToInt64(shutdown_ms_str, &shutdown_ms);
  file_util::Delete(shutdown_ms_file, false);

  if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0)
    return;

  const char *time_fmt = "Shutdown.%s.time";
  const char *time_per_fmt = "Shutdown.%s.time_per_process";
  std::string time;
  std::string time_per;
  if (type == WINDOW_CLOSE) {
    time = base::StringPrintf(time_fmt, "window_close");
    time_per = base::StringPrintf(time_per_fmt, "window_close");
  } else if (type == BROWSER_EXIT) {
    time = base::StringPrintf(time_fmt, "browser_exit");
    time_per = base::StringPrintf(time_per_fmt, "browser_exit");
  } else if (type == END_SESSION) {
    time = base::StringPrintf(time_fmt, "end_session");
    time_per = base::StringPrintf(time_per_fmt, "end_session");
  } else {
    NOTREACHED();
  }

  if (time.empty())
    return;

  // TODO(erikkay): change these to UMA histograms after a bit more testing.
  UMA_HISTOGRAM_TIMES(time.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms));
  UMA_HISTOGRAM_TIMES(time_per.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms / num_procs));
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs);
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow);
}

void ReadLastShutdownInfo() {
  PrefService* prefs = g_browser_process->local_state();
  ShutdownType type =
      static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType));
  int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses);
  int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow);
  // clear the prefs immediately so we don't pick them up on a future run
  prefs->SetInteger(prefs::kShutdownType, NOT_VALID);
  prefs->SetInteger(prefs::kShutdownNumProcesses, 0);
  prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0);

  // Read and delete the file on the file thread.
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadLastShutdownFile, type, num_procs, num_procs_slow));
}

void SetTryingToQuit(bool quitting) {
  g_trying_to_quit = quitting;
}

bool IsTryingToQuit() {
  return g_trying_to_quit;
}

bool ShuttingDownWithoutClosingBrowsers() {
  return g_shutting_down_without_closing_browsers;
}

void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
  g_shutting_down_without_closing_browsers = without_close;
}

}  // namespace browser_shutdown
<commit_msg>get rid of static initializer shutdown_started_<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_shutdown.h"

#include <map>
#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "build/build_config.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/switch_utils.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_WIN)
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
#include "chrome/browser/rlz/rlz.h"
#endif

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#endif

using base::Time;
using base::TimeDelta;
using content::BrowserThread;

namespace browser_shutdown {

// Whether the browser is trying to quit (e.g., Quit chosen from menu).
bool g_trying_to_quit = false;

// Whether the browser should quit without closing browsers.
bool g_shutting_down_without_closing_browsers = false;

Time* shutdown_started_ = NULL;
ShutdownType shutdown_type_ = NOT_VALID;
int shutdown_num_processes_;
int shutdown_num_processes_slow_;

bool delete_resources_on_shutdown = true;

const char kShutdownMsFile[] = "chrome_shutdown_ms.txt";

void RegisterPrefs(PrefService* local_state) {
  local_state->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0);
}

ShutdownType GetShutdownType() {
  return shutdown_type_;
}

void OnShutdownStarting(ShutdownType type) {
  if (shutdown_type_ != NOT_VALID)
    return;

  shutdown_type_ = type;
  // For now, we're only counting the number of renderer processes
  // since we can't safely count the number of plugin processes from this
  // thread, and we'd really like to avoid anything which might add further
  // delays to shutdown time.
  DCHECK(!shutdown_started_);
  shutdown_started_ = new Time(Time::Now());

  // Call FastShutdown on all of the RenderProcessHosts.  This will be
  // a no-op in some cases, so we still need to go through the normal
  // shutdown path for the ones that didn't exit here.
  shutdown_num_processes_ = 0;
  shutdown_num_processes_slow_ = 0;
  for (content::RenderProcessHost::iterator i(
          content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    ++shutdown_num_processes_;
    if (!i.GetCurrentValue()->FastShutdownIfPossible())
      ++shutdown_num_processes_slow_;
  }
}

FilePath GetShutdownMsPath() {
  FilePath shutdown_ms_file;
  PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file);
  return shutdown_ms_file.AppendASCII(kShutdownMsFile);
}

bool ShutdownPreThreadsStop() {
#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
      "BrowserShutdownStarted", false);
#endif
  // During shutdown we will end up some blocking operations.  But the
  // work needs to get done and we're going to wait for them no matter
  // what thread they're on, so don't worry about it slowing down
  // shutdown.
  base::ThreadRestrictions::SetIOAllowed(true);

  // Shutdown the IPC channel to the service processes.
  ServiceProcessControl::GetInstance()->Disconnect();

  // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough
  // time to get here. If you have something that *must* happen on end session,
  // consider putting it in BrowserProcessImpl::EndSession.
  PrefService* prefs = g_browser_process->local_state();

  MetricsService* metrics = g_browser_process->metrics_service();
  if (metrics)
    metrics->RecordCompletedSessionEnd();

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Record the shutdown info so that we can put it into a histogram at next
    // startup.
    prefs->SetInteger(prefs::kShutdownType, shutdown_type_);
    prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_);
    prefs->SetInteger(prefs::kShutdownNumProcessesSlow,
                      shutdown_num_processes_slow_);
  }

  // Check local state for the restart flag so we can restart the session below.
  bool restart_last_session = false;
  if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) {
    restart_last_session =
        prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown);
    prefs->ClearPref(prefs::kRestartLastSessionOnShutdown);
  }

  prefs->CommitPendingWrite();

#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
  // Cleanup any statics created by RLZ. Must be done before NotificationService
  // is destroyed.
  RLZTracker::CleanupRlz();
#endif

  return restart_last_session;
}

void ShutdownPostThreadsStop(bool restart_last_session) {
  // The jank'o'meter requires that the browser process has been destroyed
  // before calling UninstallJankometer().
  delete g_browser_process;
  g_browser_process = NULL;

  // crbug.com/95079 - This needs to happen after the browser process object
  // goes away.
  ProfileManager::NukeDeletedProfilesFromDisk();

#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("BrowserDeleted",
                                                        true);
#endif

  // Uninstall Jank-O-Meter here after the IO thread is no longer running.
  UninstallJankometer();

  if (delete_resources_on_shutdown)
    ResourceBundle::CleanupSharedInstance();

#if defined(OS_WIN)
  if (!browser_util::IsBrowserAlreadyRunning() &&
      shutdown_type_ != browser_shutdown::END_SESSION) {
    upgrade_util::SwapNewChromeExeIfPresent();
  }
#endif

  if (restart_last_session) {
#if !defined(OS_CHROMEOS)
    // Make sure to relaunch the browser with the original command line plus
    // the Restore Last Session flag. Note that Chrome can be launched (ie.
    // through ShellExecute on Windows) with a switch argument terminator at
    // the end (double dash, as described in b/1366444) plus a URL,
    // which prevents us from appending to the command line directly (issue
    // 46182). We therefore use GetSwitches to copy the command line (it stops
    // at the switch argument terminator).
    CommandLine old_cl(*CommandLine::ForCurrentProcess());
    scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram()));
    std::map<std::string, CommandLine::StringType> switches =
        old_cl.GetSwitches();
    // Remove the switches that shouldn't persist across restart.
    about_flags::RemoveFlagsSwitches(&switches);
    switches::RemoveSwitchesForAutostart(&switches);
    // Append the old switches to the new command line.
    for (std::map<std::string, CommandLine::StringType>::const_iterator i =
        switches.begin(); i != switches.end(); ++i) {
      CommandLine::StringType switch_value = i->second;
      if (!switch_value.empty())
        new_cl->AppendSwitchNative(i->first, i->second);
      else
        new_cl->AppendSwitch(i->first);
    }
    upgrade_util::RelaunchChromeBrowser(*new_cl.get());
#else
    NOTIMPLEMENTED();
#endif  // !defined(OS_CHROMEOS)
  }

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Measure total shutdown time as late in the process as possible
    // and then write it to a file to be read at startup.
    // We can't use prefs since all services are shutdown at this point.
    TimeDelta shutdown_delta = Time::Now() - *shutdown_started_;
    std::string shutdown_ms =
        base::Int64ToString(shutdown_delta.InMilliseconds());
    int len = static_cast<int>(shutdown_ms.length()) + 1;
    FilePath shutdown_ms_file = GetShutdownMsPath();
    file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
  }

#if defined(OS_CHROMEOS)
  BrowserList::NotifyAndTerminate(false);
#endif

  ChromeURLDataManager::DeleteDataSources();
}

void ReadLastShutdownFile(
    ShutdownType type,
    int num_procs,
    int num_procs_slow) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  FilePath shutdown_ms_file = GetShutdownMsPath();
  std::string shutdown_ms_str;
  int64 shutdown_ms = 0;
  if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str))
    base::StringToInt64(shutdown_ms_str, &shutdown_ms);
  file_util::Delete(shutdown_ms_file, false);

  if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0)
    return;

  const char *time_fmt = "Shutdown.%s.time";
  const char *time_per_fmt = "Shutdown.%s.time_per_process";
  std::string time;
  std::string time_per;
  if (type == WINDOW_CLOSE) {
    time = base::StringPrintf(time_fmt, "window_close");
    time_per = base::StringPrintf(time_per_fmt, "window_close");
  } else if (type == BROWSER_EXIT) {
    time = base::StringPrintf(time_fmt, "browser_exit");
    time_per = base::StringPrintf(time_per_fmt, "browser_exit");
  } else if (type == END_SESSION) {
    time = base::StringPrintf(time_fmt, "end_session");
    time_per = base::StringPrintf(time_per_fmt, "end_session");
  } else {
    NOTREACHED();
  }

  if (time.empty())
    return;

  // TODO(erikkay): change these to UMA histograms after a bit more testing.
  UMA_HISTOGRAM_TIMES(time.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms));
  UMA_HISTOGRAM_TIMES(time_per.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms / num_procs));
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs);
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow);
}

void ReadLastShutdownInfo() {
  PrefService* prefs = g_browser_process->local_state();
  ShutdownType type =
      static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType));
  int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses);
  int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow);
  // clear the prefs immediately so we don't pick them up on a future run
  prefs->SetInteger(prefs::kShutdownType, NOT_VALID);
  prefs->SetInteger(prefs::kShutdownNumProcesses, 0);
  prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0);

  // Read and delete the file on the file thread.
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadLastShutdownFile, type, num_procs, num_procs_slow));
}

void SetTryingToQuit(bool quitting) {
  g_trying_to_quit = quitting;
}

bool IsTryingToQuit() {
  return g_trying_to_quit;
}

bool ShuttingDownWithoutClosingBrowsers() {
  return g_shutting_down_without_closing_browsers;
}

void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
  g_shutting_down_without_closing_browsers = without_close;
}

}  // namespace browser_shutdown
<|endoftext|>


<commit_before>#include "pch.h"
#include "utils.h"

#if defined (WIN32)
#include <Rpc.h>
#elif defined (__ANDROID__)
#include <uuidlib/uuid.h>
#else
#include <uuid/uuid.h>
#endif

std::string Utils::generateUUID( )
{
    std::string s;

#ifdef WIN32
    UUID uuid;
    UuidCreate ( &uuid );

    unsigned char * str;
    UuidToStringA ( &uuid, &str );

    s = ( const char* ) str;

    RpcStringFreeA ( &str );
#else
    uuid_t uuid;
    uuid_generate_random ( uuid );
    char str[37];
    uuid_unparse ( uuid, str );

    s = str;
#endif

    return s;
}

const UChar * Utils::WCSToUString(const wchar_t * str)
{
    static UChar result[ 2048 ];

    int32_t length = 0;
    UErrorCode error = U_ZERO_ERROR;

    u_strFromWCS( result, 2048, &length, str, -1, &error );

    if( U_FAILURE( error ) )
        return NULL;

    return result;
}

const wchar_t * Utils::UTF8ToWCS(const char * str)
{
    static UChar valueUni[ 1024 ];
    int32_t length = 0;
    UErrorCode error = U_ZERO_ERROR;
    u_strFromUTF8( valueUni, 1024, &length, str, -1, &error );

    error = U_ZERO_ERROR;
    static wchar_t valueW[ 1024 ];
    u_strToWCS( valueW, 1024, &length, valueUni, -1, &error );

    return valueW;
}

const wchar_t * Utils::ANSIToWCS(const char * str)
{
    static wchar_t result[ 2048 ];

    wchar_t * o = result;
    while( *str )
        *o++ = *str++;
    *o = 0;

    return result;
}

const char * Utils::format(const char * fmt, ...)
{
    static char result[ 2048 ];

    va_list args;
    va_start(args, fmt);

#ifdef WIN32
    _vsnprintf(result, 2048, fmt, args);
#else
    vsnprintf(result, 2048, fmt, args);
#endif

    va_end(args);

    return result;
}

const wchar_t * Utils::clipTextToBounds(const wchar_t * text, float width, const gameplay::Font * font, float fontSize)
{
    static std::wstring result;

    result = text;

    float textw = 0, texth = 0;
    font->measureText( text, fontSize, &textw, &texth );
    if( textw >= width && width > 0 )
    {
        result.erase(result.end() - 1, result.end());
        result.push_back( '.' );
        result.push_back( '.' );
        result.push_back( '.' );
        do
        {
            result.erase( result.end() - 4, result.end() );
            result.push_back( '.' );
            result.push_back( '.' );
            result.push_back( '.' );
            font->measureText( result.c_str( ), fontSize, &textw, &texth );
        }
        while( textw >= width );
    }

    return result.c_str( );
}

void Utils::serializeString(gameplay::Stream * stream, const std::string& str)
{
    int32_t size = static_cast<int32_t>(str.size());
    stream->write(&size, sizeof(size), 1);
    stream->write(str.c_str(), sizeof(char), size);
}

void Utils::deserializeString(gameplay::Stream * stream, std::string& str)
{
    str.clear();
    int32_t size = 0;
    stream->read(&size, sizeof(size), 1);

    char * buf = reinterpret_cast<char *>(alloca(sizeof(char)* (size + 1)));
    if (buf)
    {
        stream->read(buf, sizeof(char), size);
        buf[size] = '\0';
        str = buf;
    }
}
<commit_msg>safety string deserialization<commit_after>#include "pch.h"
#include "utils.h"

#if defined (WIN32)
#include <Rpc.h>
#elif defined (__ANDROID__)
#include <uuidlib/uuid.h>
#else
#include <uuid/uuid.h>
#endif

std::string Utils::generateUUID( )
{
    std::string s;

#ifdef WIN32
    UUID uuid;
    UuidCreate ( &uuid );

    unsigned char * str;
    UuidToStringA ( &uuid, &str );

    s = ( const char* ) str;

    RpcStringFreeA ( &str );
#else
    uuid_t uuid;
    uuid_generate_random ( uuid );
    char str[37];
    uuid_unparse ( uuid, str );

    s = str;
#endif

    return s;
}

const UChar * Utils::WCSToUString(const wchar_t * str)
{
    static UChar result[ 2048 ];

    int32_t length = 0;
    UErrorCode error = U_ZERO_ERROR;

    u_strFromWCS( result, 2048, &length, str, -1, &error );

    if( U_FAILURE( error ) )
        return NULL;

    return result;
}

const wchar_t * Utils::UTF8ToWCS(const char * str)
{
    static UChar valueUni[ 1024 ];
    int32_t length = 0;
    UErrorCode error = U_ZERO_ERROR;
    u_strFromUTF8( valueUni, 1024, &length, str, -1, &error );

    error = U_ZERO_ERROR;
    static wchar_t valueW[ 1024 ];
    u_strToWCS( valueW, 1024, &length, valueUni, -1, &error );

    return valueW;
}

const wchar_t * Utils::ANSIToWCS(const char * str)
{
    static wchar_t result[ 2048 ];

    wchar_t * o = result;
    while( *str )
        *o++ = *str++;
    *o = 0;

    return result;
}

const char * Utils::format(const char * fmt, ...)
{
    static char result[ 2048 ];

    va_list args;
    va_start(args, fmt);

#ifdef WIN32
    _vsnprintf(result, 2048, fmt, args);
#else
    vsnprintf(result, 2048, fmt, args);
#endif

    va_end(args);

    return result;
}

const wchar_t * Utils::clipTextToBounds(const wchar_t * text, float width, const gameplay::Font * font, float fontSize)
{
    static std::wstring result;

    result = text;

    float textw = 0, texth = 0;
    font->measureText( text, fontSize, &textw, &texth );
    if( textw >= width && width > 0 )
    {
        result.erase(result.end() - 1, result.end());
        result.push_back( '.' );
        result.push_back( '.' );
        result.push_back( '.' );
        do
        {
            result.erase( result.end() - 4, result.end() );
            result.push_back( '.' );
            result.push_back( '.' );
            result.push_back( '.' );
            font->measureText( result.c_str( ), fontSize, &textw, &texth );
        }
        while( textw >= width );
    }

    return result.c_str( );
}

void Utils::serializeString(gameplay::Stream * stream, const std::string& str)
{
    int32_t size = static_cast<int32_t>(str.size());
    stream->write(&size, sizeof(size), 1);
    stream->write(str.c_str(), sizeof(char), size);
}

void Utils::deserializeString(gameplay::Stream * stream, std::string& str)
{
    str.clear();
    int32_t size = 0;
    if (stream->read(&size, sizeof(size), 1) != 1)
        return;

    if (size < 0 || size > 65535)
        return; // something wrong with data

    char * buf = reinterpret_cast<char *>(alloca(sizeof(char)* (size + 1)));
    if (buf)
    {
        stream->read(buf, sizeof(char), size);
        buf[size] = '\0';
        str = buf;
    }
}
<|endoftext|>