<commit_before>/*
 * Copyright (c) 2012, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <oskar_global.h>
#include <interferometry/oskar_visibilities_read.h>
#include <interferometry/oskar_visibilities_init.h>
#include <interferometry/oskar_visibilities_write.h>
#include <interferometry/oskar_visibilities_copy.h>
#include <utility/oskar_get_error_string.h>
#include <utility/oskar_mem_add.h>

#include "extern/ezOptionParser-0.2.0/ezOptionParser.hpp"

#include <string>
#include <cmath>
#include <iostream>
#include <cfloat>

using namespace ez;
using namespace std;

void set_options(ezOptionParser& opt);
void print_usage(ezOptionParser& opt);
bool check_options(ezOptionParser& opt);
bool isCompatible(const oskar_Visibilities& vis1, const oskar_Visibilities& vis2);
void add_visibilities(oskar_Visibilities& out, const oskar_Visibilities& in1,
        const oskar_Visibilities& in2);
void print_error(int status, const char* message);

int main(int argc, const char** argv)
{
    // Register options =======================================================
    ezOptionParser opt;
    set_options(opt);
    opt.parse(argc, argv);
    if (!check_options(opt))
        return 1;

    // Capture options ========================================================
    string in1_path, in2_path, out_path;
    bool visFirst = ((int)opt.firstArgs.size() == 3) &&
            ((int)opt.lastArgs.size() == 0);
    if (visFirst) {
        in1_path = *opt.firstArgs[1];
        in2_path = *opt.firstArgs[2];
    }
    else {
        in1_path = *opt.lastArgs[0];
        in2_path = *opt.lastArgs[1];
    }
    opt.get("-o")->getString(out_path);

    cout << "in1 = " << in1_path << endl;
    cout << "in2 = " << in2_path << endl;
    cout << "out = " << out_path << endl;

    // Load input data ========================================================
    int status = OSKAR_SUCCESS;
    oskar_Visibilities in1_vis;
    oskar_Visibilities in2_vis;
    oskar_visibilities_read(&in1_vis, in1_path.c_str(), &status);
    oskar_visibilities_read(&in2_vis, in2_path.c_str(), &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed to read visibility data files.");

    // Sanity checks ==========================================================
    int vis1_n = in1_vis.num_baselines * in1_vis.num_times * in1_vis.num_channels;
    int vis2_n = in2_vis.num_baselines * in2_vis.num_times * in2_vis.num_channels;

    cout << "vis1 num data points = " << vis1_n << endl;
    cout << "vis2 num data points = " << vis2_n << endl;

    // TODO get this to return a more useful message.!
    if (!isCompatible(in1_vis, in2_vis))
    {
        cerr << "ERROR: Input visibility data must match!" << endl;
        return 1;
    }
    // TODO handle cases where they are not compatible but can be concatenated?

    // Create output data =====================================================
    int amp_type = in1_vis.amplitude.type;
    int num_channels = in1_vis.num_channels;
    int num_times = in1_vis.num_times;
    int num_stations = in1_vis.num_stations;
    oskar_Visibilities out_vis;
    oskar_visibilities_init(&out_vis, amp_type, OSKAR_LOCATION_CPU, num_channels,
            num_times, num_stations, &status);
    oskar_visibilities_copy(&out_vis, &in1_vis, &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed to initialise output visibility structure.");

    // Add ====================================================================
    add_visibilities(out_vis, in1_vis, in2_vis);

    // Write output data ======================================================
    oskar_visibilities_write(&out_vis, 0, out_path.c_str(), &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed writing output visibility structure to file.");

    return 0;
}

void print_error(int status, const char* message)
{
    cerr << "ERROR[" << status << "] " << message << endl;
    cerr << "REASON = " << oskar_get_error_string(status) << endl;
}

void add_visibilities(oskar_Visibilities& out, const oskar_Visibilities& in1,
        const oskar_Visibilities& in2)
{
    int status = OSKAR_SUCCESS;
    oskar_mem_add(&out.amplitude, &in1.amplitude, &in2.amplitude, &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Visibility amplitude addition failed.");
}

bool isCompatible(const oskar_Visibilities& v1, const oskar_Visibilities& v2)
{
    if (v1.num_channels != v2.num_channels)
        return false;
    if (v1.num_times != v2.num_times)
        return false;
    if (v1.num_stations != v2.num_stations)
        return false;
    if (v1.num_baselines != v2.num_baselines)
        return false;
    if (fabs(v1.freq_start_hz - v2.freq_start_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.freq_inc_hz - v2.freq_inc_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.channel_bandwidth_hz - v2.channel_bandwidth_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.time_start_mjd_utc - v2.time_start_mjd_utc) > DBL_EPSILON)
        return false;
    if (fabs(v1.time_inc_seconds - v2.time_inc_seconds) > DBL_EPSILON)
        return false;
    if (fabs(v1.phase_centre_ra_deg - v2.phase_centre_ra_deg) > DBL_EPSILON)
        return false;
    if (fabs(v1.phase_centre_dec_deg - v2.phase_centre_dec_deg) > DBL_EPSILON)
        return false;

    if (v1.amplitude.type != v2.amplitude.type)
        return false;

    return true;
}

void print_usage(ezOptionParser& opt)
{
    string usage;
    opt.getUsage(usage);
    cout << usage;
}

void set_options(ezOptionParser& opt)
{
    opt.overview = string(80, '-') + "\n" +
            "OSKAR application to combine visibility files" +
            "\n" + string(80, '-');
    opt.syntax = "\n  $ oskar_visibilities_add [OPTIONS] input1.vis input2.vis";
    opt.example =
            "  $ oskar_visibilities_add file1.vis file2.vis\n"
            "\n"
            ;
    opt.footer =
            "|" + std::string(80, '-') + "\n"
            "| OSKAR (version " + OSKAR_VERSION_STR + ")\n"
            "| Copyright (C) 2012, The University of Oxford.\n"
            "| This program is free and without warranty.\n"
            "|" + std::string(80, '-') + "\n";
    // add(default, required?, num args, delimiter, msg, flag token(s), ...)
    opt.add("", 0, 0, 0, "Display usage instructions.",
            "-h", "-help", "--help", "--usage");
    opt.add("", 0, 0, 0, "Display the OSKAR version.",
            "-v", "--version");
    opt.add("out.vis", 0, 1, 0, "Output visibility filename (optional, default=out.vis).",
            "-o", "--output");
}

bool check_options(ezOptionParser& opt)
{
    if (opt.isSet("-h")) {
        print_usage(opt);
        return false;
    }

    if (opt.isSet("-v")) {
         cout << "OSKAR version " <<OSKAR_VERSION_STR << endl;
         return false;
    }

    std::vector<std::string> badOptions;
    if(!opt.gotRequired(badOptions)) {
        for(int i=0; i < (int)badOptions.size(); ++i)
            cerr << "ERROR: Missing required option " << badOptions[i] << ".\n\n";
        print_usage(opt);
        return false;
    }

    if(!opt.gotExpected(badOptions)) {
        for(int i=0; i < (int)badOptions.size(); ++i)
        {
            cerr << "ERROR: Got unexpected number of arguments for option ";
            cerr << badOptions[i] << ".\n\n";
        }
        print_usage(opt);
        return false;
    }

    bool visFirst = ((int)opt.firstArgs.size() == 3) &&
            ((int)opt.lastArgs.size() == 0);
    bool visEnd = ((int)opt.firstArgs.size() == 1) &&
            ((int)opt.lastArgs.size() == 2);
    if (!visFirst && !visEnd) {
        print_usage(opt);
        return false;
    }

    return true;
}

<commit_msg>updated interface to allow the addition of more than 2 visibility files though either a list or by the use of wildcards<commit_after>/*
 * Copyright (c) 2012, The University of Oxford
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Oxford nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <oskar_global.h>
#include <interferometry/oskar_visibilities_read.h>
#include <interferometry/oskar_visibilities_init.h>
#include <interferometry/oskar_visibilities_write.h>
#include <interferometry/oskar_visibilities_copy.h>
#include <utility/oskar_get_error_string.h>
#include <utility/oskar_mem_add.h>

#include "extern/ezOptionParser-0.2.0/ezOptionParser.hpp"

#include <string>
#include <cmath>
#include <iostream>
#include <cfloat>
#include <vector>
#include <iomanip>

using namespace ez;
using namespace std;

// -----------------------------------------------------------------------------
void set_options(ezOptionParser& opt);
void print_usage(ezOptionParser& opt);
bool check_options(ezOptionParser& opt);
vector<string> getInputFiles(ezOptionParser& opt);
bool isCompatible(const oskar_Visibilities& vis1, const oskar_Visibilities& vis2);
void add_visibilities(oskar_Visibilities& out, const oskar_Visibilities& in1,
        const oskar_Visibilities& in2);
void print_error(int status, const char* message);
// -----------------------------------------------------------------------------

int main(int argc, const char** argv)
{
    // Register options =======================================================
    ezOptionParser opt;
    set_options(opt);
    opt.parse(argc, argv);
    if (!check_options(opt))
        return 1;

    // Capture options ========================================================
    string out_path;
    opt.get("-o")->getString(out_path);
    vector<string> in_files = getInputFiles(opt);
    cout << "Output visibility file = " << out_path << endl;
    cout << "Combining the " << in_files.size() << " input files:" << endl;
    for (int i = 0; i < (int)in_files.size(); ++i) {
        cout << "  [" << setw(2) << i << "] " << in_files[i] << endl;
    }

    // Add the data. ==========================================================
    int status = OSKAR_SUCCESS;

    // Load the first visibility structure.
    oskar_Visibilities in1;
    oskar_visibilities_read(&in1, in_files[0].c_str(), &status);
    int amp_type = in1.amplitude.type;
    int num_channels = in1.num_channels;
    int num_times = in1.num_times;
    int num_stations = in1.num_stations;
    if (status != OSKAR_SUCCESS) {
        string msg = "Failed to read visibility data file " + in_files[0];
        print_error(status, msg.c_str());
    }

    // Create an output visibility data structure.
    oskar_Visibilities out;
    oskar_visibilities_init(&out, amp_type, OSKAR_LOCATION_CPU, num_channels,
            num_times, num_stations, &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed to initialise output visibility structure.");

    // Copy the first input visibility data file into the output data structure.
    oskar_visibilities_copy(&out, &in1, &status);

    // Loop over other visibility files and combine.
    for (int i = 1; i < (int)in_files.size(); ++i)
    {
        oskar_Visibilities in2;
        oskar_visibilities_read(&in2, in_files[i].c_str(), &status);
        if (status != OSKAR_SUCCESS) {
            string msg = "Failed to read visibility data file " + in_files[i];
            print_error(status, msg.c_str());
        }
        if (!isCompatible(out, in2))
        {
            cerr << "ERROR: Input visibility data must match!" << endl;
            return 1;
        }
        add_visibilities(out, out, in2);
    }
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed to read visibility data files.");

    // Write output data ======================================================
    oskar_visibilities_write(&out, 0, out_path.c_str(), &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Failed writing output visibility structure to file.");

    return 0;
}

vector<string> getInputFiles(ezOptionParser& opt)
{
    vector<string> files;
    bool visFirst = ((int)opt.firstArgs.size() >= 3) &&
            ((int)opt.lastArgs.size() == 0);

    if (visFirst)
    {
        // Note starts at 1 as index 0 == the program name.
        for (int i = 1; i < (int)opt.firstArgs.size(); ++i)
        {
            files.push_back(*opt.firstArgs[i]);
        }
    }
    else
    {
        for (int i = 0; i < (int)opt.lastArgs.size(); ++i)
        {
            files.push_back(*opt.lastArgs[i]);
        }
    }

    return files;
}

void print_error(int status, const char* message)
{
    cerr << "ERROR[" << status << "] " << message << endl;
    cerr << "REASON = " << oskar_get_error_string(status) << endl;
}

void add_visibilities(oskar_Visibilities& out, const oskar_Visibilities& in1,
        const oskar_Visibilities& in2)
{
    int status = OSKAR_SUCCESS;
    oskar_mem_add(&out.amplitude, &in1.amplitude, &in2.amplitude, &status);
    if (status != OSKAR_SUCCESS)
        print_error(status, "Visibility amplitude addition failed.");
}

bool isCompatible(const oskar_Visibilities& v1, const oskar_Visibilities& v2)
{
    if (v1.num_channels != v2.num_channels)
        return false;
    if (v1.num_times != v2.num_times)
        return false;
    if (v1.num_stations != v2.num_stations)
        return false;
    if (v1.num_baselines != v2.num_baselines)
        return false;
    if (fabs(v1.freq_start_hz - v2.freq_start_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.freq_inc_hz - v2.freq_inc_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.channel_bandwidth_hz - v2.channel_bandwidth_hz) > DBL_EPSILON)
        return false;
    if (fabs(v1.time_start_mjd_utc - v2.time_start_mjd_utc) > DBL_EPSILON)
        return false;
    if (fabs(v1.time_inc_seconds - v2.time_inc_seconds) > DBL_EPSILON)
        return false;
    if (fabs(v1.phase_centre_ra_deg - v2.phase_centre_ra_deg) > DBL_EPSILON)
        return false;
    if (fabs(v1.phase_centre_dec_deg - v2.phase_centre_dec_deg) > DBL_EPSILON)
        return false;

    if (v1.amplitude.type != v2.amplitude.type)
        return false;

    return true;
}

void print_usage(ezOptionParser& opt)
{
    string usage;
    opt.getUsage(usage);
    cout << usage;
}

void set_options(ezOptionParser& opt)
{
    opt.overview = string(80, '-') + "\n" +
            "OSKAR application to combine visibility files" +
            "\n" + string(80, '-');
    opt.syntax = "\n  $ oskar_visibilities_add [OPTIONS] inputFile(s)...";
    opt.example =
            "  $ oskar_visibilities_add file1.vis file2.vis\n"
            "  $ oskar_visibilities_add file1.vis file2.vis -o combined.vis\n"
            "  $ oskar_visibilities_add file1.vis file2.vis file3.vis\n"
            "  $ oskar_visibilities_add *.vis\n"
            "\n"
            ;
    opt.footer =
            "|" + std::string(80, '-') + "\n"
            "| OSKAR (version " + OSKAR_VERSION_STR + ")\n"
            "| Copyright (C) 2012, The University of Oxford.\n"
            "| This program is free and without warranty.\n"
            "|" + std::string(80, '-') + "\n";
    // add(default, required?, num args, delimiter, msg, flag token(s), ...)
    opt.add("", 0, 0, 0, "Display usage instructions.",
            "-h", "-help", "--help", "--usage");
    opt.add("", 0, 0, 0, "Display the OSKAR version.",
            "-v", "--version");
    opt.add("out.vis", 0, 1, 0, "Output visibility filename (optional, default=out.vis).",
            "-o", "--output");
}

bool check_options(ezOptionParser& opt)
{
    if (opt.isSet("-h")) {
        print_usage(opt);
        return false;
    }

    if (opt.isSet("-v")) {
         cout << "OSKAR version " <<OSKAR_VERSION_STR << endl;
         return false;
    }

    std::vector<std::string> badOptions;
    if(!opt.gotRequired(badOptions)) {
        for(int i=0; i < (int)badOptions.size(); ++i)
            cerr << "\nERROR: Missing required option " << badOptions[i] << ".\n\n";
        print_usage(opt);
        return false;
    }

    if(!opt.gotExpected(badOptions)) {
        for(int i=0; i < (int)badOptions.size(); ++i)
        {
            cerr << "\nERROR: Got unexpected number of arguments for option ";
            cerr << badOptions[i] << ".\n\n";
        }
        print_usage(opt);
        return false;
    }

    bool visFirst = ((int)opt.firstArgs.size() >= 3) &&
            ((int)opt.lastArgs.size() == 0);
    bool visEnd = ((int)opt.firstArgs.size() == 1) &&
            ((int)opt.lastArgs.size() >= 2);
    if (!visFirst && !visEnd) {
        cerr << "\nERROR: Please provide 2 or more visibility files to combine.\n\n";
        print_usage(opt);
        return false;
    }

    return true;
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "LuaStack.h"
#include "LuaEnvironment.h"
#include "World.h"
#include "Device.h"

namespace crown
{

//-----------------------------------------------------------------------------
CE_EXPORT int world_spawn_unit(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);
	const char* name = stack.get_string(2);

	const Vector3& pos = stack.num_args() > 2 ? stack.get_vector3(3) : Vector3::ZERO;
	const Quaternion& rot = stack.num_args() > 3 ? stack.get_quaternion(4) : Quaternion::IDENTITY;

	UnitId unit = world->spawn_unit(name, pos, rot);

	stack.push_unit(world->lookup_unit(unit));
	return 1;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_mesh(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	stack.push_mesh(world->mesh());
	return 1;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_play_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);
	const char* name = stack.get_string(2);

	const bool loop = stack.num_args() > 2 ? stack.get_bool(3) : false;
	const float volume = stack.num_args() > 3 ? stack.get_float(4) : 1.0f; // test value
	const Vector3& pos = stack.num_args() > 4 ? stack.get_vector3(5) : Vector3::ZERO;
	const float range = stack.num_args() > 5 ? stack.get_float(6) : 1000.0f; // test value

	SoundInstanceId id = world->play_sound(name, loop, volume, pos, range);

	stack.push_int32(id.encode());

	return 1;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_pause_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	world->pause_sound(id);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_link_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	SoundInstanceId sound;
	sound.decode(stack.get_int(2));

	UnitId unit;
	unit.decode(stack.get_int(3));

	world->link_sound(sound, unit);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_listener(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	const Vector3& pos = stack.get_vector3(2);
	const Vector3& vel = stack.get_vector3(3);
	const Vector3& or_up = stack.get_vector3(4);
	const Vector3& or_at = stack.get_vector3(5);

	world->set_listener(pos, vel, or_up, or_at);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_position(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	const Vector3& pos = stack.get_vector3(3);

	world->set_sound_position(id, pos);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_range(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	float range = stack.get_float(3);

	world->set_sound_range(id, range);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_volume(lua_State* L)
{
	LuaStack stack(L);

	World* world = (World*) stack.get_lightdata(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));
	float vol = stack.get_float(3);

	world->set_sound_volume(id, vol);

	return 0;
}

//-----------------------------------------------------------------------------
void load_world(LuaEnvironment& env)
{
	env.load_module_function("World", "spawn_unit",			world_spawn_unit);

	env.load_module_function("World", "play_sound",			world_play_sound);
	env.load_module_function("World", "pause_sound", 		world_pause_sound);
	env.load_module_function("World", "link_sound",			world_link_sound);
	env.load_module_function("World", "set_listener", 		world_set_listener);
	env.load_module_function("World", "set_sound_position", world_set_sound_position);
	env.load_module_function("World", "set_sound_range", 	world_set_sound_range);
	env.load_module_function("World", "set_sound_volume", 	world_set_sound_volume);

	// GARBAGE
	env.load_module_function("World", "mesh", world_mesh);
}

} // namespace crown<commit_msg>Use get_world and remove garbage<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include "LuaStack.h"
#include "LuaEnvironment.h"
#include "World.h"
#include "Device.h"

namespace crown
{

//-----------------------------------------------------------------------------
CE_EXPORT int world_spawn_unit(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);
	const char* name = stack.get_string(2);

	const Vector3& pos = stack.num_args() > 2 ? stack.get_vector3(3) : Vector3::ZERO;
	const Quaternion& rot = stack.num_args() > 3 ? stack.get_quaternion(4) : Quaternion::IDENTITY;

	UnitId unit = world->spawn_unit(name, pos, rot);

	stack.push_unit(world->lookup_unit(unit));
	return 1;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_play_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);
	const char* name = stack.get_string(2);

	const bool loop = stack.num_args() > 2 ? stack.get_bool(3) : false;
	const float volume = stack.num_args() > 3 ? stack.get_float(4) : 1.0f; // test value
	const Vector3& pos = stack.num_args() > 4 ? stack.get_vector3(5) : Vector3::ZERO;
	const float range = stack.num_args() > 5 ? stack.get_float(6) : 1000.0f; // test value

	SoundInstanceId id = world->play_sound(name, loop, volume, pos, range);

	stack.push_int32(id.encode());

	return 1;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_pause_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	world->pause_sound(id);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_link_sound(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	SoundInstanceId sound;
	sound.decode(stack.get_int(2));

	UnitId unit;
	unit.decode(stack.get_int(3));

	world->link_sound(sound, unit);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_listener(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	const Vector3& pos = stack.get_vector3(2);
	const Vector3& vel = stack.get_vector3(3);
	const Vector3& or_up = stack.get_vector3(4);
	const Vector3& or_at = stack.get_vector3(5);

	world->set_listener(pos, vel, or_up, or_at);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_position(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	const Vector3& pos = stack.get_vector3(3);

	world->set_sound_position(id, pos);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_range(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));

	float range = stack.get_float(3);

	world->set_sound_range(id, range);

	return 0;
}

//-----------------------------------------------------------------------------
CE_EXPORT int world_set_sound_volume(lua_State* L)
{
	LuaStack stack(L);

	World* world = stack.get_world(1);

	SoundInstanceId id;
	id.decode(stack.get_int(2));
	float vol = stack.get_float(3);

	world->set_sound_volume(id, vol);

	return 0;
}

//-----------------------------------------------------------------------------
void load_world(LuaEnvironment& env)
{
	env.load_module_function("World", "spawn_unit",			world_spawn_unit);

	env.load_module_function("World", "play_sound",			world_play_sound);
	env.load_module_function("World", "pause_sound", 		world_pause_sound);
	env.load_module_function("World", "link_sound",			world_link_sound);
	env.load_module_function("World", "set_listener", 		world_set_listener);
	env.load_module_function("World", "set_sound_position", world_set_sound_position);
	env.load_module_function("World", "set_sound_range", 	world_set_sound_range);
	env.load_module_function("World", "set_sound_volume", 	world_set_sound_volume);
}

} // namespace crown<|endoftext|>


<commit_before>/*
 *  _____             ___ ___   |
 * |  _  |___ ___ _ _|_  |_  |  |  C/C++ framework for 32-bit AVRs
 * |     | -_|  _| | |_  |  _|  |
 * |__|__|___|_| |_  |___|___|  |  https://github.com/aery32
 *               |___|          |
 *
 * Copyright (c) 2012, Muiku Oy
 * All rights reserved.
 *
 * LICENSE
 *
 * New BSD License, see the LICENSE.txt bundled with this package. If you did
 * not receive a copy of the license and are unable to obtain it through the
 * world-wide-web, please send an email to contact@muiku.com so we can send
 * you a copy.
 */

#include "aery32/adc.h"
#include "aery32/pm.h"

volatile avr32_adc_t *aery::adc = &AVR32_ADC;
volatile uint32_t aery::__adc_lsr = AVR32_ADC.sr;

int aery::adc_init(uint8_t prescal, bool hires, uint8_t shtime,
		uint8_t startup)
{
	uint32_t adclk;

	if (prescal > 63)
		return -1;
	AVR32_ADC.CR.swrst = 1;
	adclk = aery::pm_get_fclkdomain(CLKDOMAIN_PBA) / (2 * (prescal + 1));

	switch (hires) {
	case true:
		if (adclk > ADCLK_HIRES_MAX)
			return -1;
		break;
	case false:
		if (adclk > ADCLK_LORES_MAX)
			return -1;
		break;
	}

	AVR32_ADC.MR.prescal = prescal;
	AVR32_ADC.MR.shtim = shtime & ~0xf0;
	AVR32_ADC.MR.startup = startup & ~0xe0;
	AVR32_ADC.MR.sleep = 0;
	AVR32_ADC.MR.lowres = !hires;
	AVR32_ADC.MR.trgen = 0;

	return 0;
}

void aery::adc_setup_trigger(enum Adc_trigger trigger)
{
	AVR32_ADC.MR.trgen = 1;
	AVR32_ADC.MR.trgsel = trigger;
}

void aery::adc_enable(uint8_t chamask)
{
	AVR32_ADC.cher = chamask;
}

void aery::adc_disable(uint8_t chamask)
{
	AVR32_ADC.chdr = chamask;
}

void aery::adc_start_cnv(void)
{
	AVR32_ADC.CR.start = true;
}

int aery::adc_isbusy(uint8_t chamask)
{
	using namespace aery;

	__adc_lsr = AVR32_ADC.sr;
	if (AVR32_ADC.chsr == 0 || (AVR32_ADC.chsr & chamask) != chamask)
		return -1;
	if (chamask == 0)
		return (__adc_lsr & AVR32_ADC_SR_DRDY_MASK) == 0;
	return (__adc_lsr & chamask) == chamask;
}

uint16_t aery::adc_read_cnv(uint8_t chanum)
{
	return *(&(AVR32_ADC.cdr0) + chanum);
}

uint16_t aery::adc_read_lastcnv(void)
{
	return AVR32_ADC.lcdr;
}

bool adc_has_overrun(uint8_t chamask)
{
	using namespace aery;
	if (chamask == 0)
		return (__adc_lsr & AVR32_ADC_GOVRE_MASK);
	return (__adc_lsr & (chamask << AVR32_ADC_OVRE0_OFFSET));
}<commit_msg>Just reorder adc functions<commit_after>/*
 *  _____             ___ ___   |
 * |  _  |___ ___ _ _|_  |_  |  |  C/C++ framework for 32-bit AVRs
 * |     | -_|  _| | |_  |  _|  |
 * |__|__|___|_| |_  |___|___|  |  https://github.com/aery32
 *               |___|          |
 *
 * Copyright (c) 2012, Muiku Oy
 * All rights reserved.
 *
 * LICENSE
 *
 * New BSD License, see the LICENSE.txt bundled with this package. If you did
 * not receive a copy of the license and are unable to obtain it through the
 * world-wide-web, please send an email to contact@muiku.com so we can send
 * you a copy.
 */

#include "aery32/adc.h"
#include "aery32/pm.h"

volatile avr32_adc_t *aery::adc = &AVR32_ADC;
volatile uint32_t aery::__adc_lsr = AVR32_ADC.sr;

int aery::adc_init(uint8_t prescal, bool hires, uint8_t shtime,
		uint8_t startup)
{
	uint32_t adclk;

	if (prescal > 63)
		return -1;
	AVR32_ADC.CR.swrst = 1;
	adclk = aery::pm_get_fclkdomain(CLKDOMAIN_PBA) / (2 * (prescal + 1));

	switch (hires) {
	case true:
		if (adclk > ADCLK_HIRES_MAX)
			return -1;
		break;
	case false:
		if (adclk > ADCLK_LORES_MAX)
			return -1;
		break;
	}

	AVR32_ADC.MR.prescal = prescal;
	AVR32_ADC.MR.shtim = shtime & ~0xf0;
	AVR32_ADC.MR.startup = startup & ~0xe0;
	AVR32_ADC.MR.sleep = 0;
	AVR32_ADC.MR.lowres = !hires;
	AVR32_ADC.MR.trgen = 0;

	return 0;
}

void aery::adc_setup_trigger(enum Adc_trigger trigger)
{
	AVR32_ADC.MR.trgen = 1;
	AVR32_ADC.MR.trgsel = trigger;
}

void aery::adc_start_cnv(void)
{
	AVR32_ADC.CR.start = true;
}

uint16_t aery::adc_read_cnv(uint8_t chanum)
{
	return *(&(AVR32_ADC.cdr0) + chanum);
}

uint16_t aery::adc_read_lastcnv(void)
{
	return AVR32_ADC.lcdr;
}

void aery::adc_enable(uint8_t chamask)
{
	AVR32_ADC.cher = chamask;
}

void aery::adc_disable(uint8_t chamask)
{
	AVR32_ADC.chdr = chamask;
}

int aery::adc_isbusy(uint8_t chamask)
{
	using namespace aery;

	__adc_lsr = AVR32_ADC.sr;
	if (AVR32_ADC.chsr == 0 || (AVR32_ADC.chsr & chamask) != chamask)
		return -1;
	if (chamask == 0)
		return (__adc_lsr & AVR32_ADC_SR_DRDY_MASK) == 0;
	return (__adc_lsr & chamask) == chamask;
}

bool adc_has_overrun(uint8_t chamask)
{
	using namespace aery;
	if (chamask == 0)
		return (__adc_lsr & AVR32_ADC_GOVRE_MASK);
	return (__adc_lsr & (chamask << AVR32_ADC_OVRE0_OFFSET));
}<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors All Rights Reserved.

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

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

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

#include "tensorflow/contrib/tpu/profiler/dump_tpu_profile.h"

#include <cstdio>
#include <ctime>
#include <vector>

#include "tensorflow/contrib/tpu/profiler/op_profile.pb.h"
#include "tensorflow/contrib/tpu/profiler/trace_events.pb.h"
#include "tensorflow/contrib/tpu/profiler/trace_events_to_json.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/io/compression.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/protobuf/config.pb.h"
#include "tensorflow/core/util/event.pb.h"
#include "tensorflow/core/util/events_writer.h"

namespace tensorflow {
namespace tpu {
namespace {

using ::tensorflow::io::JoinPath;
using ::tensorflow::protobuf::util::JsonOptions;
using ::tensorflow::protobuf::util::MessageToJsonString;

constexpr char kGraphRunPrefix[] = "tpu_profiler.hlo_graph.";
constexpr char kJsonOpProfileFileName[] = "op_profile.json";
constexpr char kJsonTraceFileName[] = "trace.json.gz";
constexpr char kProfilePluginDirectory[] = "plugins/profile/";
constexpr char kProtoTraceFileName[] = "trace";

Status WriteGzippedDataToFile(const string& filename, const string& data) {
  std::unique_ptr<WritableFile> file;
  TF_RETURN_IF_ERROR(Env::Default()->NewWritableFile(filename, &file));
  io::ZlibCompressionOptions options = io::ZlibCompressionOptions::GZIP();
  io::ZlibOutputBuffer buffer(file.get(), options.input_buffer_size,
                              options.output_buffer_size, options);
  TF_RETURN_IF_ERROR(buffer.Init());
  TF_RETURN_IF_ERROR(buffer.Append(data));
  TF_RETURN_IF_ERROR(buffer.Close());
  TF_RETURN_IF_ERROR(file->Close());
  return Status::OK();
}

Status DumpTraceToLogDirectory(StringPiece run_dir, const string& encoded_trace,
                               std::ostream* os) {
  string proto_path = JoinPath(run_dir, kProtoTraceFileName);
  TF_RETURN_IF_ERROR(
      WriteStringToFile(Env::Default(), proto_path, encoded_trace));
  LOG(INFO) << "Dumped raw-proto trace data to " << proto_path;

  string json_path = JoinPath(run_dir, kJsonTraceFileName);
  Trace trace;
  trace.ParseFromString(encoded_trace);
  *os << "Trace contains " << trace.trace_events_size() << " events."
      << std::endl;
  TF_RETURN_IF_ERROR(
      WriteGzippedDataToFile(json_path, TraceEventsToJson(trace)));
  *os << "Dumped JSON trace data to " << json_path << std::endl;
  return Status::OK();
}

Status DumpOpProfileToLogDirectory(StringPiece run_dir,
                                   const tpu::op_profile::Profile& profile,
                                   std::ostream* os) {
  string path = JoinPath(run_dir, kJsonOpProfileFileName);
  string json;
  JsonOptions options;
  options.always_print_primitive_fields = true;
  auto status = MessageToJsonString(profile, &json, options);
  if (!status.ok()) {
    return errors::Internal(
        "Failed to convert op profile to json. Skipping... ",
        string(status.error_message()));
  }
  TF_RETURN_IF_ERROR(WriteStringToFile(Env::Default(), path, json));
  *os << "Dumped json op profile data to " << path << std::endl;
  return Status::OK();
}

Status DumpToolDataToLogDirectory(StringPiece run_dir,
                                  const tensorflow::ProfileToolData& tool,
                                  std::ostream* os) {
  string path = JoinPath(run_dir, tool.name());
  TF_RETURN_IF_ERROR(WriteStringToFile(Env::Default(), path, tool.data()));
  *os << "Dumped tool data for " << tool.name() << " to " << path << std::endl;
  return Status::OK();
}

Status DumpGraphEvents(const string& logdir, const string& run,
                       const ProfileResponse& response, std::ostream* os) {
  int num_graphs = response.computation_graph_size();
  if (response.computation_graph_size() == 0) return Status::OK();
  // The server might generates multiple graphs for one program; we simply
  // pick the first one.
  if (num_graphs > 1) {
    *os << num_graphs
        << " TPU program variants observed over the profiling period. "
        << "One computation graph will be chosen arbitrarily." << std::endl;
  }
  // The graph plugin expects the graph in <logdir>/<run>/<event.file>.
  string run_dir = JoinPath(logdir, strings::StrCat(kGraphRunPrefix, run));
  TF_RETURN_IF_ERROR(Env::Default()->RecursivelyCreateDir(run_dir));
  EventsWriter event_writer(JoinPath(run_dir, "events"));
  Event event;
  // Add the computation graph.
  event.set_graph_def(response.computation_graph(0).SerializeAsString());
  event_writer.WriteEvent(event);
  *os << "Wrote a HLO graph to " << event_writer.FileName() << std::endl;

  if (response.has_hlo_metadata()) {
    tensorflow::TaggedRunMetadata tagged_run_metadata;
    tagged_run_metadata.set_tag(run);
    tagged_run_metadata.set_run_metadata(
        response.hlo_metadata().SerializeAsString());
    tensorflow::Event meta_event;
    *meta_event.mutable_tagged_run_metadata() = tagged_run_metadata;
    event_writer.WriteEvent(meta_event);
    *os << "Wrote HLO ops run metadata to " << event_writer.FileName()
        << std::endl;
  }
  return Status::OK();
}

}  // namespace

Status WriteTensorboardTPUProfile(const string& logdir, const string& run,
                                  const ProfileResponse& response,
                                  std::ostream* os) {
  // Dumps profile data to <logdir>/plugins/profile/<run>/.
  string profile_run_dir = JoinPath(logdir, kProfilePluginDirectory, run);
  TF_RETURN_IF_ERROR(Env::Default()->RecursivelyCreateDir(profile_run_dir));
  // Ignore computation_graph for now.
  if (response.encoded_trace().empty()) {
    *os << "No trace event is collected." << std::endl;
  } else {
    LOG(INFO) << "Converting trace events to TraceViewer JSON.";
    TF_RETURN_IF_ERROR(
        DumpTraceToLogDirectory(profile_run_dir, response.encoded_trace(), os));
  }
  if (response.has_op_profile() &&
      (response.op_profile().has_by_program_structure() ||
       response.op_profile().has_by_category())) {
    TF_RETURN_IF_ERROR(DumpOpProfileToLogDirectory(profile_run_dir,
                                                   response.op_profile(), os));
  }
  if (!response.tool_data().empty()) {
    for (const auto& tool_data : response.tool_data()) {
      TF_RETURN_IF_ERROR(
          DumpToolDataToLogDirectory(profile_run_dir, tool_data, os));
    }
  }
  TF_RETURN_IF_ERROR(DumpGraphEvents(logdir, run, response, os));

  return Status::OK();
}

}  // namespace tpu
}  // namespace tensorflow
<commit_msg>   [tpu:profiler] Do not generate output files from other cloud tools if no trace is collected.<commit_after>/* Copyright 2017 The TensorFlow Authors All Rights Reserved.

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

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

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

#include "tensorflow/contrib/tpu/profiler/dump_tpu_profile.h"

#include <cstdio>
#include <ctime>
#include <vector>

#include "tensorflow/contrib/tpu/profiler/op_profile.pb.h"
#include "tensorflow/contrib/tpu/profiler/trace_events.pb.h"
#include "tensorflow/contrib/tpu/profiler/trace_events_to_json.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/io/compression.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/protobuf/config.pb.h"
#include "tensorflow/core/util/event.pb.h"
#include "tensorflow/core/util/events_writer.h"

namespace tensorflow {
namespace tpu {
namespace {

using ::tensorflow::io::JoinPath;
using ::tensorflow::protobuf::util::JsonOptions;
using ::tensorflow::protobuf::util::MessageToJsonString;

constexpr char kGraphRunPrefix[] = "tpu_profiler.hlo_graph.";
constexpr char kJsonOpProfileFileName[] = "op_profile.json";
constexpr char kJsonTraceFileName[] = "trace.json.gz";
constexpr char kProfilePluginDirectory[] = "plugins/profile/";
constexpr char kProtoTraceFileName[] = "trace";

Status WriteGzippedDataToFile(const string& filename, const string& data) {
  std::unique_ptr<WritableFile> file;
  TF_RETURN_IF_ERROR(Env::Default()->NewWritableFile(filename, &file));
  io::ZlibCompressionOptions options = io::ZlibCompressionOptions::GZIP();
  io::ZlibOutputBuffer buffer(file.get(), options.input_buffer_size,
                              options.output_buffer_size, options);
  TF_RETURN_IF_ERROR(buffer.Init());
  TF_RETURN_IF_ERROR(buffer.Append(data));
  TF_RETURN_IF_ERROR(buffer.Close());
  TF_RETURN_IF_ERROR(file->Close());
  return Status::OK();
}

Status DumpTraceToLogDirectory(StringPiece run_dir, const string& encoded_trace,
                               std::ostream* os) {
  string proto_path = JoinPath(run_dir, kProtoTraceFileName);
  TF_RETURN_IF_ERROR(
      WriteStringToFile(Env::Default(), proto_path, encoded_trace));
  LOG(INFO) << "Dumped raw-proto trace data to " << proto_path;

  string json_path = JoinPath(run_dir, kJsonTraceFileName);
  Trace trace;
  trace.ParseFromString(encoded_trace);
  *os << "Trace contains " << trace.trace_events_size() << " events."
      << std::endl;
  TF_RETURN_IF_ERROR(
      WriteGzippedDataToFile(json_path, TraceEventsToJson(trace)));
  *os << "Dumped JSON trace data to " << json_path << std::endl;
  return Status::OK();
}

Status DumpOpProfileToLogDirectory(StringPiece run_dir,
                                   const tpu::op_profile::Profile& profile,
                                   std::ostream* os) {
  string path = JoinPath(run_dir, kJsonOpProfileFileName);
  string json;
  JsonOptions options;
  options.always_print_primitive_fields = true;
  auto status = MessageToJsonString(profile, &json, options);
  if (!status.ok()) {
    return errors::Internal(
        "Failed to convert op profile to json. Skipping... ",
        string(status.error_message()));
  }
  TF_RETURN_IF_ERROR(WriteStringToFile(Env::Default(), path, json));
  *os << "Dumped json op profile data to " << path << std::endl;
  return Status::OK();
}

Status DumpToolDataToLogDirectory(StringPiece run_dir,
                                  const tensorflow::ProfileToolData& tool,
                                  std::ostream* os) {
  string path = JoinPath(run_dir, tool.name());
  TF_RETURN_IF_ERROR(WriteStringToFile(Env::Default(), path, tool.data()));
  *os << "Dumped tool data for " << tool.name() << " to " << path << std::endl;
  return Status::OK();
}

Status DumpGraphEvents(const string& logdir, const string& run,
                       const ProfileResponse& response, std::ostream* os) {
  int num_graphs = response.computation_graph_size();
  if (response.computation_graph_size() == 0) return Status::OK();
  // The server might generates multiple graphs for one program; we simply
  // pick the first one.
  if (num_graphs > 1) {
    *os << num_graphs
        << " TPU program variants observed over the profiling period. "
        << "One computation graph will be chosen arbitrarily." << std::endl;
  }
  // The graph plugin expects the graph in <logdir>/<run>/<event.file>.
  string run_dir = JoinPath(logdir, strings::StrCat(kGraphRunPrefix, run));
  TF_RETURN_IF_ERROR(Env::Default()->RecursivelyCreateDir(run_dir));
  EventsWriter event_writer(JoinPath(run_dir, "events"));
  Event event;
  // Add the computation graph.
  event.set_graph_def(response.computation_graph(0).SerializeAsString());
  event_writer.WriteEvent(event);
  *os << "Wrote a HLO graph to " << event_writer.FileName() << std::endl;

  if (response.has_hlo_metadata()) {
    tensorflow::TaggedRunMetadata tagged_run_metadata;
    tagged_run_metadata.set_tag(run);
    tagged_run_metadata.set_run_metadata(
        response.hlo_metadata().SerializeAsString());
    tensorflow::Event meta_event;
    *meta_event.mutable_tagged_run_metadata() = tagged_run_metadata;
    event_writer.WriteEvent(meta_event);
    *os << "Wrote HLO ops run metadata to " << event_writer.FileName()
        << std::endl;
  }
  return Status::OK();
}

}  // namespace

Status WriteTensorboardTPUProfile(const string& logdir, const string& run,
                                  const ProfileResponse& response,
                                  std::ostream* os) {
  // Dumps profile data to <logdir>/plugins/profile/<run>/.
  string profile_run_dir = JoinPath(logdir, kProfilePluginDirectory, run);
  TF_RETURN_IF_ERROR(Env::Default()->RecursivelyCreateDir(profile_run_dir));

  // Ignore computation_graph for now.
  const bool empty_trace = response.encoded_trace().empty();
  if (empty_trace) {
    *os << "No trace event is collected." << std::endl;
  } else {
    LOG(INFO) << "Converting trace events to TraceViewer JSON.";
    TF_RETURN_IF_ERROR(
        DumpTraceToLogDirectory(profile_run_dir, response.encoded_trace(), os));
  }
  if (response.has_op_profile() &&
      (response.op_profile().has_by_program_structure() ||
       response.op_profile().has_by_category())) {
    TF_RETURN_IF_ERROR(DumpOpProfileToLogDirectory(profile_run_dir,
                                                   response.op_profile(), os));
  }
  if (!empty_trace && !response.tool_data().empty()) {
    for (const auto& tool_data : response.tool_data()) {
      TF_RETURN_IF_ERROR(
          DumpToolDataToLogDirectory(profile_run_dir, tool_data, os));
    }
  }
  TF_RETURN_IF_ERROR(DumpGraphEvents(logdir, run, response, os));

  return Status::OK();
}

}  // namespace tpu
}  // namespace tensorflow
<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2009-2011 Matthias Kretz <kretz@kde.org>

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

    Vc 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 Lesser General Public License for more details.

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

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>

using namespace Vc;

template<typename Vec> void maskedGatherArray()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    typedef typename Vec::Mask M;

    T mem[Vec::Size];
    for (int i = 0; i < Vec::Size; ++i) {
        mem[i] = i + 1;
    }

    It indexes = It::IndexesFromZero();
    for_all_masks(Vec, m) {
        const Vec a(mem, indexes, m);
        for (int j = 0; j < Vec::Size; ++j) {
            COMPARE(a[j], m[j] ? mem[j] : 0) << " j = " << j << ", m = " << m;
        }

        T x = Vec::Size + 1;
        Vec b = x;
        b.gather(mem, indexes, m);
        for (int j = 0; j < Vec::Size; ++j) {
            COMPARE(b[j], m[j] ? mem[j] : x) << " j = " << j << ", m = " << m;
        }
    }
}

template<typename Vec> void gatherArray()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    typedef typename It::Mask M;

    const int count = 39999;
    T array[count];
    for (int i = 0; i < count; ++i) {
        array[i] = i + 1;
    }
    M mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        const Vec ii(i + 1);
        const typename Vec::Mask castedMask = static_cast<typename Vec::Mask>(mask);
        if (castedMask.isFull()) {
            Vec a(array, i);
            COMPARE(a, ii) << "\n       i: " << i;
            Vec b(Zero);
            b.gather(array, i);
            COMPARE(b, ii);
            COMPARE(a, b);
        }
        Vec b(Zero);
        b.gather(array, i, castedMask);
        COMPARE(castedMask, b == ii);
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
    }

    const typename Vec::Mask k(Zero);
    Vec a(One);
    a.gather(array, It(IndexesFromZero), k);
    COMPARE(a, Vec(One));
}

template<typename T> struct Struct
{
    T a;
    char x;
    T b;
    short y;
    T c;
    char z;
};

template<typename Vec> void gatherStruct()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    typedef Struct<T> S;
    const int count = 3999;
    S array[count];
    for (int i = 0; i < count; ++i) {
        array[i].a = i;
        array[i].b = i + 1;
        array[i].c = i + 2;
    }
    typename It::Mask mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        // if Vec is double_v the cast keeps only the lower two values, which is why the ==
        // comparison works
        const Vec i0(i);
        const Vec i1(i + 1);
        const Vec i2(i + 2);
        const typename Vec::Mask castedMask(mask);

        if (castedMask.isFull()) {
            Vec a(array, &S::a, i);
            COMPARE(a, i0) << "\ni: " << i;
            a.gather(array, &S::b, i);
            COMPARE(a, i1);
            a.gather(array, &S::c, i);
            COMPARE(a, i2);
        }

        Vec b(Zero);
        b.gather(array, &S::a, i, castedMask);
        COMPARE(castedMask, (b == i0));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
        b.gather(array, &S::b, i, castedMask);
        COMPARE(castedMask, (b == i1));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
        b.gather(array, &S::c, i, castedMask);
        COMPARE(castedMask, (b == i2));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
    }
}

template<typename T> struct Row
{
    T *data;
};

template<typename Vec> void gather2dim()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    const int count = 399;
    typedef Row<T> S;
    S array[count];
    for (int i = 0; i < count; ++i) {
        array[i].data = new T[count];
        for (int j = 0; j < count; ++j) {
            array[i].data[j] = 2 * i + j + 1;
        }
    }

    typename It::Mask mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        for (It j = It(IndexesFromZero); !(mask &= (j < count)).isEmpty(); j += Vec::Size) {
            const Vec i0(i * 2 + j + 1);
            const typename Vec::Mask castedMask(mask);

            Vec a(array, &S::data, i, j, castedMask);
            COMPARE(castedMask, castedMask && (a == i0));

            Vec b(Zero);
            b.gather(array, &S::data, i, j, castedMask);
            COMPARE(castedMask, (b == i0));
            if (!castedMask.isFull()) {
                COMPARE(!castedMask, b == Vec(Zero));
            } else {
                Vec c(array, &S::data, i, j);
                VERIFY((c == i0).isFull());

                Vec d(Zero);
                d.gather(array, &S::data, i, j);
                VERIFY((d == i0).isFull());
            }
        }
    }
    for (int i = 0; i < count; ++i) {
        delete[] array[i].data;
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(gatherArray);
    testAllTypes(maskedGatherArray);
    testAllTypes(gatherStruct);
    testAllTypes(gather2dim);

    return 0;
}
<commit_msg>small cleanup<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2009-2011 Matthias Kretz <kretz@kde.org>

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

    Vc 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 Lesser General Public License for more details.

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

*/

#include <Vc/Vc>
#include "unittest.h"
#include <iostream>

using namespace Vc;

template<typename Vec> void maskedGatherArray()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;

    T mem[Vec::Size];
    for (int i = 0; i < Vec::Size; ++i) {
        mem[i] = i + 1;
    }

    It indexes = It::IndexesFromZero();
    for_all_masks(Vec, m) {
        const Vec a(mem, indexes, m);
        for (int i = 0; i < Vec::Size; ++i) {
            COMPARE(a[i], m[i] ? mem[i] : 0) << " i = " << i << ", m = " << m;
        }

        T x = Vec::Size + 1;
        Vec b = x;
        b.gather(mem, indexes, m);
        for (int i = 0; i < Vec::Size; ++i) {
            COMPARE(b[i], m[i] ? mem[i] : x) << " i = " << i << ", m = " << m;
        }
    }
}

template<typename Vec> void gatherArray()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    typedef typename It::Mask M;

    const int count = 39999;
    T array[count];
    for (int i = 0; i < count; ++i) {
        array[i] = i + 1;
    }
    M mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        const Vec ii(i + 1);
        const typename Vec::Mask castedMask = static_cast<typename Vec::Mask>(mask);
        if (castedMask.isFull()) {
            Vec a(array, i);
            COMPARE(a, ii) << "\n       i: " << i;
            Vec b(Zero);
            b.gather(array, i);
            COMPARE(b, ii);
            COMPARE(a, b);
        }
        Vec b(Zero);
        b.gather(array, i, castedMask);
        COMPARE(castedMask, b == ii);
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
    }

    const typename Vec::Mask k(Zero);
    Vec a(One);
    a.gather(array, It(IndexesFromZero), k);
    COMPARE(a, Vec(One));
}

template<typename T> struct Struct
{
    T a;
    char x;
    T b;
    short y;
    T c;
    char z;
};

template<typename Vec> void gatherStruct()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    typedef Struct<T> S;
    const int count = 3999;
    S array[count];
    for (int i = 0; i < count; ++i) {
        array[i].a = i;
        array[i].b = i + 1;
        array[i].c = i + 2;
    }
    typename It::Mask mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        // if Vec is double_v the cast keeps only the lower two values, which is why the ==
        // comparison works
        const Vec i0(i);
        const Vec i1(i + 1);
        const Vec i2(i + 2);
        const typename Vec::Mask castedMask(mask);

        if (castedMask.isFull()) {
            Vec a(array, &S::a, i);
            COMPARE(a, i0) << "\ni: " << i;
            a.gather(array, &S::b, i);
            COMPARE(a, i1);
            a.gather(array, &S::c, i);
            COMPARE(a, i2);
        }

        Vec b(Zero);
        b.gather(array, &S::a, i, castedMask);
        COMPARE(castedMask, (b == i0));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
        b.gather(array, &S::b, i, castedMask);
        COMPARE(castedMask, (b == i1));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
        b.gather(array, &S::c, i, castedMask);
        COMPARE(castedMask, (b == i2));
        if (!castedMask.isFull()) {
            COMPARE(!castedMask, b == Vec(Zero));
        }
    }
}

template<typename T> struct Row
{
    T *data;
};

template<typename Vec> void gather2dim()
{
    typedef typename Vec::IndexType It;
    typedef typename Vec::EntryType T;
    const int count = 399;
    typedef Row<T> S;
    S array[count];
    for (int i = 0; i < count; ++i) {
        array[i].data = new T[count];
        for (int j = 0; j < count; ++j) {
            array[i].data[j] = 2 * i + j + 1;
        }
    }

    typename It::Mask mask;
    for (It i = It(IndexesFromZero); !(mask = (i < count)).isEmpty(); i += Vec::Size) {
        for (It j = It(IndexesFromZero); !(mask &= (j < count)).isEmpty(); j += Vec::Size) {
            const Vec i0(i * 2 + j + 1);
            const typename Vec::Mask castedMask(mask);

            Vec a(array, &S::data, i, j, castedMask);
            COMPARE(castedMask, castedMask && (a == i0));

            Vec b(Zero);
            b.gather(array, &S::data, i, j, castedMask);
            COMPARE(castedMask, (b == i0));
            if (!castedMask.isFull()) {
                COMPARE(!castedMask, b == Vec(Zero));
            } else {
                Vec c(array, &S::data, i, j);
                VERIFY((c == i0).isFull());

                Vec d(Zero);
                d.gather(array, &S::data, i, j);
                VERIFY((d == i0).isFull());
            }
        }
    }
    for (int i = 0; i < count; ++i) {
        delete[] array[i].data;
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(gatherArray);
    testAllTypes(maskedGatherArray);
    testAllTypes(gatherStruct);
    testAllTypes(gather2dim);

    return 0;
}
<|endoftext|>


<commit_before>#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>

using namespace eosio;
using namespace testing;
using namespace chain;

BOOST_AUTO_TEST_SUITE(block_tests)

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
{
   tester main;

   // First we create a valid block with valid transaction
   main.create_account("newacc"_n);
   auto b = main.produce_block();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(std::move(*b));
   auto signed_tx = signed_transaction( std::get<packed_transaction>(copy_b->transactions.back().trx).to_packed_transaction_v0()->get_signed_transaction() );
   auto& act = signed_tx.actions.back();
   auto act_data = act.data_as<newaccount>();
   // Make the transaction invalid by having the new account name the same as the creator name
   act_data.name = act_data.creator;
   act.data = fc::raw::pack(act_data);
   // Re-sign the transaction
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(config::system_account_name, "active"), main.control->get_chain_id());
   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(std::move(signed_tx), true);
   copy_b->transactions.back().trx = std::move(invalid_packed_tx);

   // Re-calculate the transaction merkle
   deque<digest_type> trx_digests;
   const auto& trxs = copy_b->transactions;
   for( const auto& a : trxs )
      trx_digests.emplace_back( a.digest() );
   copy_b->transaction_mroot = merkle( move(trx_digests) );

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);

   // Push block with invalid transaction to other chain
   tester validator;
   auto bs = validator.control->create_block_state_future( copy_b->calculate_id(), copy_b );
   validator.control->abort_block();
   BOOST_REQUIRE_EXCEPTION(validator.control->push_block( bs, forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception ,
   [] (const fc::exception &e)->bool {
      return e.code() == account_name_exists_exception::code_value ;
   }) ;

}

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
{
   tester main;

   // First we create a valid block with valid transaction
   main.create_account(N(newacc));
   auto b = main.produce_block();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(std::move(*b));
   auto signed_tx = copy_b->transactions.back().trx.get<packed_transaction>().get_signed_transaction();

   // Change the transaction that will be run
   signed_tx.actions[0].name = N(something);
   // Re-sign the transaction
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(config::system_account_name, "active"), main.control->get_chain_id());
   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(signed_tx);
   copy_b->transactions.back().trx = invalid_packed_tx;

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);

   // Push block with invalid transaction to other chain
   tester validator;
   auto bs = validator.control->create_block_state_future( copy_b );
   validator.control->abort_block();
   BOOST_REQUIRE_EXCEPTION(validator.control->push_block( bs, forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception ,
                           [] (const fc::exception &e)->bool {
                              return e.code() == block_validate_exception::code_value &&
                                     e.to_detail_string().find("invalid block transaction merkle root") != std::string::npos;
                           }) ;
}

std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block(validating_tester& main, account_name act_name) {
   // First we create a valid block with valid transaction
   main.create_account(act_name);
   signed_block_ptr b = main.produce_block_no_validation();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(b->clone());
   const auto& packed_trx = std::get<packed_transaction>(copy_b->transactions.back().trx);
   auto signed_tx = signed_transaction( packed_trx.to_packed_transaction_v0()->get_signed_transaction() );
   // Corrupt one signature
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(act_name, "active"), main.control->get_chain_id());

   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(std::move(signed_tx), true, packed_trx.get_compression());
   copy_b->transactions.back().trx = std::move(invalid_packed_tx);

   // Re-calculate the transaction merkle
   deque<digest_type> trx_digests;
   const auto& trxs = copy_b->transactions;
   for( const auto& a : trxs )
      trx_digests.emplace_back( a.digest() );
   copy_b->transaction_mroot = merkle( move(trx_digests) );

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(sig_digest);
   return std::pair<signed_block_ptr, signed_block_ptr>(b, copy_b);
}

// verify that a block with a transaction with an incorrect signature, is blindly accepted from a trusted producer
BOOST_AUTO_TEST_CASE(trusted_producer_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducera"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   main.validate_push_block( blocks.second );
}

// like trusted_producer_test, except verify that any entry in the trusted_producer list is accepted
BOOST_AUTO_TEST_CASE(trusted_producer_verify_2nd_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducerc"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   main.validate_push_block( blocks.second );
}

// verify that a block with a transaction with an incorrect signature, is rejected if it is not from a trusted producer
BOOST_AUTO_TEST_CASE(untrusted_producer_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducerb"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   BOOST_REQUIRE_EXCEPTION(main.validate_push_block( blocks.second ), fc::exception ,
   [] (const fc::exception &e)->bool {
      return e.code() == unsatisfied_authorization::code_value ;
   }) ;
}

/**
 * Ensure that the block broadcasted by producing node and receiving node is identical
 */
BOOST_AUTO_TEST_CASE(broadcasted_block_test)
{

  tester producer_node;
  tester receiving_node;

  signed_block_ptr bcasted_blk_by_prod_node;
  signed_block_ptr bcasted_blk_by_recv_node;

  producer_node.control->accepted_block.connect( [&](const block_state_ptr& bs) {
    bcasted_blk_by_prod_node = bs->block;
  });
  receiving_node.control->accepted_block.connect( [&](const block_state_ptr& bs) {
    bcasted_blk_by_recv_node = bs->block;
  });

  auto b = producer_node.produce_block();
  receiving_node.push_block(b);

  bytes bcasted_blk_by_prod_node_packed = fc::raw::pack(*bcasted_blk_by_prod_node);
  bytes bcasted_blk_by_recv_node_packed = fc::raw::pack(*bcasted_blk_by_recv_node);
  BOOST_CHECK(std::equal(bcasted_blk_by_prod_node_packed.begin(), bcasted_blk_by_prod_node_packed.end(), bcasted_blk_by_recv_node_packed.begin()));
}

/**
 * Verify abort block returns applied transactions in block
 */
BOOST_FIXTURE_TEST_CASE( abort_block_transactions, validating_tester) { try {

      produce_blocks(2);
      signed_transaction trx;

      account_name a = "newco"_n;
      account_name creator = config::system_account_name;

      // account does not exist before test
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      auto owner_auth = authority( get_public_key( a, "owner" ) );
      trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
                                newaccount{
                                      .creator  = creator,
                                      .name     = a,
                                      .owner    = owner_auth,
                                      .active   = authority( get_public_key( a, "active" ) )
                                });
      set_transaction_headers(trx);
      trx.sign( get_private_key( creator, "active" ), control->get_chain_id()  );
      auto trace = push_transaction( trx );

      control->get_account( a ); // throws if it does not exist

      auto unapplied_trxs = control->abort_block();

      // verify transaction returned from abort_block()
      BOOST_REQUIRE_EQUAL( 1,  unapplied_trxs.size() );
      BOOST_REQUIRE_EQUAL( trx.id(), unapplied_trxs.at(0)->id() );

      // account does not exist block was aborted which had transaction
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      produce_blocks(1);

   } FC_LOG_AND_RETHROW() }

/**
 * Verify abort block returns applied transactions in block
 */
BOOST_FIXTURE_TEST_CASE( abort_block_transactions_tester, validating_tester) { try {

      produce_blocks(2);
      signed_transaction trx;

      account_name a = "newco"_n;
      account_name creator = config::system_account_name;

      // account does not exist before test
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      auto owner_auth = authority( get_public_key( a, "owner" ) );
      trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
                                newaccount{
                                      .creator  = creator,
                                      .name     = a,
                                      .owner    = owner_auth,
                                      .active   = authority( get_public_key( a, "active" ) )
                                });
      set_transaction_headers(trx);
      trx.sign( get_private_key( creator, "active" ), control->get_chain_id()  );
      auto trace = push_transaction( trx );

      control->get_account( a ); // throws if it does not exist

      produce_block( fc::milliseconds(config::block_interval_ms*2) ); // aborts block, tester should reapply trx

      control->get_account( a ); // throws if it does not exist

      auto unapplied_trxs = control->abort_block(); // should be empty now

      BOOST_REQUIRE_EQUAL( 0,  unapplied_trxs.size() );

   } FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Update for new packed_transaciton and N() macro<commit_after>#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>

using namespace eosio;
using namespace testing;
using namespace chain;

BOOST_AUTO_TEST_SUITE(block_tests)

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_test)
{
   tester main;

   // First we create a valid block with valid transaction
   main.create_account("newacc"_n);
   auto b = main.produce_block();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(std::move(*b));
   auto signed_tx = signed_transaction( std::get<packed_transaction>(copy_b->transactions.back().trx).to_packed_transaction_v0()->get_signed_transaction() );
   auto& act = signed_tx.actions.back();
   auto act_data = act.data_as<newaccount>();
   // Make the transaction invalid by having the new account name the same as the creator name
   act_data.name = act_data.creator;
   act.data = fc::raw::pack(act_data);
   // Re-sign the transaction
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(config::system_account_name, "active"), main.control->get_chain_id());
   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(std::move(signed_tx), true);
   copy_b->transactions.back().trx = std::move(invalid_packed_tx);

   // Re-calculate the transaction merkle
   deque<digest_type> trx_digests;
   const auto& trxs = copy_b->transactions;
   for( const auto& a : trxs )
      trx_digests.emplace_back( a.digest() );
   copy_b->transaction_mroot = merkle( move(trx_digests) );

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);

   // Push block with invalid transaction to other chain
   tester validator;
   auto bs = validator.control->create_block_state_future( copy_b->calculate_id(), copy_b );
   validator.control->abort_block();
   BOOST_REQUIRE_EXCEPTION(validator.control->push_block( bs, forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception ,
   [] (const fc::exception &e)->bool {
      return e.code() == account_name_exists_exception::code_value ;
   }) ;

}

BOOST_AUTO_TEST_CASE(block_with_invalid_tx_mroot_test)
{
   tester main;

   // First we create a valid block with valid transaction
   main.create_account("newacc"_n);
   auto b = main.produce_block();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(std::move(*b));
   const auto& packed_trx = std::get<packed_transaction>(copy_b->transactions.back().trx);
   auto signed_tx = signed_transaction( packed_trx.to_packed_transaction_v0()->get_signed_transaction() );

   // Change the transaction that will be run
   signed_tx.actions[0].name = "something"_n;
   // Re-sign the transaction
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(config::system_account_name, "active"), main.control->get_chain_id());
   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(std::move(signed_tx), true, packed_trx.get_compression());
   copy_b->transactions.back().trx = std::move(invalid_packed_tx);

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(config::system_account_name, "active").sign(sig_digest);

   // Push block with invalid transaction to other chain
   tester validator;
   auto bs = validator.control->create_block_state_future( copy_b->calculate_id(), copy_b );
   validator.control->abort_block();
   BOOST_REQUIRE_EXCEPTION(validator.control->push_block( bs, forked_branch_callback{}, trx_meta_cache_lookup{} ), fc::exception ,
                           [] (const fc::exception &e)->bool {
                              return e.code() == block_validate_exception::code_value &&
                                     e.to_detail_string().find("invalid block transaction merkle root") != std::string::npos;
                           }) ;
}

std::pair<signed_block_ptr, signed_block_ptr> corrupt_trx_in_block(validating_tester& main, account_name act_name) {
   // First we create a valid block with valid transaction
   main.create_account(act_name);
   signed_block_ptr b = main.produce_block_no_validation();

   // Make a copy of the valid block and corrupt the transaction
   auto copy_b = std::make_shared<signed_block>(b->clone());
   const auto& packed_trx = std::get<packed_transaction>(copy_b->transactions.back().trx);
   auto signed_tx = signed_transaction( packed_trx.to_packed_transaction_v0()->get_signed_transaction() );
   // Corrupt one signature
   signed_tx.signatures.clear();
   signed_tx.sign(main.get_private_key(act_name, "active"), main.control->get_chain_id());

   // Replace the valid transaction with the invalid transaction
   auto invalid_packed_tx = packed_transaction(std::move(signed_tx), true, packed_trx.get_compression());
   copy_b->transactions.back().trx = std::move(invalid_packed_tx);

   // Re-calculate the transaction merkle
   deque<digest_type> trx_digests;
   const auto& trxs = copy_b->transactions;
   for( const auto& a : trxs )
      trx_digests.emplace_back( a.digest() );
   copy_b->transaction_mroot = merkle( move(trx_digests) );

   // Re-sign the block
   auto header_bmroot = digest_type::hash( std::make_pair( copy_b->digest(), main.control->head_block_state()->blockroot_merkle.get_root() ) );
   auto sig_digest = digest_type::hash( std::make_pair(header_bmroot, main.control->head_block_state()->pending_schedule.schedule_hash) );
   copy_b->producer_signature = main.get_private_key(b->producer, "active").sign(sig_digest);
   return std::pair<signed_block_ptr, signed_block_ptr>(b, copy_b);
}

// verify that a block with a transaction with an incorrect signature, is blindly accepted from a trusted producer
BOOST_AUTO_TEST_CASE(trusted_producer_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducera"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   main.validate_push_block( blocks.second );
}

// like trusted_producer_test, except verify that any entry in the trusted_producer list is accepted
BOOST_AUTO_TEST_CASE(trusted_producer_verify_2nd_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducerc"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   main.validate_push_block( blocks.second );
}

// verify that a block with a transaction with an incorrect signature, is rejected if it is not from a trusted producer
BOOST_AUTO_TEST_CASE(untrusted_producer_test)
{
   flat_set<account_name> trusted_producers = { "defproducera"_n, "defproducerc"_n };
   validating_tester main(trusted_producers);
   // only using validating_tester to keep the 2 chains in sync, not to validate that the validating_node matches the main node,
   // since it won't be
   main.skip_validate = true;

   // First we create a valid block with valid transaction
   std::set<account_name> producers = { "defproducera"_n, "defproducerb"_n, "defproducerc"_n, "defproducerd"_n };
   for (auto prod : producers)
       main.create_account(prod);
   auto b = main.produce_block();

   std::vector<account_name> schedule(producers.cbegin(), producers.cend());
   auto trace = main.set_producers(schedule);

   while (b->producer != "defproducerb"_n) {
      b = main.produce_block();
   }

   auto blocks = corrupt_trx_in_block(main, "tstproducera"_n);
   BOOST_REQUIRE_EXCEPTION(main.validate_push_block( blocks.second ), fc::exception ,
   [] (const fc::exception &e)->bool {
      return e.code() == unsatisfied_authorization::code_value ;
   }) ;
}

/**
 * Ensure that the block broadcasted by producing node and receiving node is identical
 */
BOOST_AUTO_TEST_CASE(broadcasted_block_test)
{

  tester producer_node;
  tester receiving_node;

  signed_block_ptr bcasted_blk_by_prod_node;
  signed_block_ptr bcasted_blk_by_recv_node;

  producer_node.control->accepted_block.connect( [&](const block_state_ptr& bs) {
    bcasted_blk_by_prod_node = bs->block;
  });
  receiving_node.control->accepted_block.connect( [&](const block_state_ptr& bs) {
    bcasted_blk_by_recv_node = bs->block;
  });

  auto b = producer_node.produce_block();
  receiving_node.push_block(b);

  bytes bcasted_blk_by_prod_node_packed = fc::raw::pack(*bcasted_blk_by_prod_node);
  bytes bcasted_blk_by_recv_node_packed = fc::raw::pack(*bcasted_blk_by_recv_node);
  BOOST_CHECK(std::equal(bcasted_blk_by_prod_node_packed.begin(), bcasted_blk_by_prod_node_packed.end(), bcasted_blk_by_recv_node_packed.begin()));
}

/**
 * Verify abort block returns applied transactions in block
 */
BOOST_FIXTURE_TEST_CASE( abort_block_transactions, validating_tester) { try {

      produce_blocks(2);
      signed_transaction trx;

      account_name a = "newco"_n;
      account_name creator = config::system_account_name;

      // account does not exist before test
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      auto owner_auth = authority( get_public_key( a, "owner" ) );
      trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
                                newaccount{
                                      .creator  = creator,
                                      .name     = a,
                                      .owner    = owner_auth,
                                      .active   = authority( get_public_key( a, "active" ) )
                                });
      set_transaction_headers(trx);
      trx.sign( get_private_key( creator, "active" ), control->get_chain_id()  );
      auto trace = push_transaction( trx );

      control->get_account( a ); // throws if it does not exist

      auto unapplied_trxs = control->abort_block();

      // verify transaction returned from abort_block()
      BOOST_REQUIRE_EQUAL( 1,  unapplied_trxs.size() );
      BOOST_REQUIRE_EQUAL( trx.id(), unapplied_trxs.at(0)->id() );

      // account does not exist block was aborted which had transaction
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      produce_blocks(1);

   } FC_LOG_AND_RETHROW() }

/**
 * Verify abort block returns applied transactions in block
 */
BOOST_FIXTURE_TEST_CASE( abort_block_transactions_tester, validating_tester) { try {

      produce_blocks(2);
      signed_transaction trx;

      account_name a = "newco"_n;
      account_name creator = config::system_account_name;

      // account does not exist before test
      BOOST_REQUIRE_EXCEPTION(control->get_account( a ), fc::exception,
                              [a] (const fc::exception& e)->bool {
                                 return std::string( e.what() ).find( a.to_string() ) != std::string::npos;
                              }) ;

      auto owner_auth = authority( get_public_key( a, "owner" ) );
      trx.actions.emplace_back( vector<permission_level>{{creator,config::active_name}},
                                newaccount{
                                      .creator  = creator,
                                      .name     = a,
                                      .owner    = owner_auth,
                                      .active   = authority( get_public_key( a, "active" ) )
                                });
      set_transaction_headers(trx);
      trx.sign( get_private_key( creator, "active" ), control->get_chain_id()  );
      auto trace = push_transaction( trx );

      control->get_account( a ); // throws if it does not exist

      produce_block( fc::milliseconds(config::block_interval_ms*2) ); // aborts block, tester should reapply trx

      control->get_account( a ); // throws if it does not exist

      auto unapplied_trxs = control->abort_block(); // should be empty now

      BOOST_REQUIRE_EQUAL( 0,  unapplied_trxs.size() );

   } FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright 2013 The Flutter 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/trace-provider/provider.h>
#include <lib/trace/event.h>

#include "dart_runner.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "logging.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/tempfs.h"
#include "third_party/dart/runtime/include/dart_api.h"

#if !defined(FUCHSIA_SDK)
#include <lib/syslog/cpp/logger.h>
#endif  //  !defined(FUCHSIA_SDK)

#if !defined(DART_PRODUCT)
// Register native symbol information for the Dart VM's profiler.
static void RegisterProfilerSymbols(const char* symbols_path,
                                    const char* dso_name) {
  std::string* symbols = new std::string();
  if (dart_utils::ReadFileToString(symbols_path, symbols)) {
    Dart_AddSymbols(dso_name, symbols->data(), symbols->size());
  } else {
    FML_LOG(ERROR) << "Failed to load " << symbols_path;
    FML_CHECK(false);
  }
}
#endif  // !defined(DART_PRODUCT)

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

#if !defined(FUCHSIA_SDK)
  syslog::InitLogger();

  std::unique_ptr<trace::TraceProviderWithFdio> provider;
  {
    TRACE_EVENT0("dart", "CreateTraceProvider");
    bool already_started;
    // Use CreateSynchronously to prevent loss of early events.
    trace::TraceProviderWithFdio::CreateSynchronously(
        loop.dispatcher(), "dart_runner", &provider, &already_started);
  }
#endif  //  !defined(FUCHSIA_SDK)

#if !defined(DART_PRODUCT)
#if defined(AOT_RUNTIME)
  RegisterProfilerSymbols("pkg/data/dart_aot_runner.dartprofilersymbols", "");
#else
  RegisterProfilerSymbols("pkg/data/dart_jit_runner.dartprofilersymbols", "");
#endif  // defined(AOT_RUNTIME)
#endif  // !defined(DART_PRODUCT)

  dart_utils::RunnerTemp runner_temp;
  dart_runner::DartRunner runner;
  loop.Run();
  return 0;
}
<commit_msg>[dart_runner] Initialize logging and tracing (#13829)<commit_after>// Copyright 2013 The Flutter 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/syslog/global.h>
#include <lib/trace-provider/provider.h>
#include <lib/trace/event.h>

#include "dart_runner.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "logging.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/tempfs.h"
#include "third_party/dart/runtime/include/dart_api.h"

#if !defined(DART_PRODUCT)
// Register native symbol information for the Dart VM's profiler.
static void RegisterProfilerSymbols(const char* symbols_path,
                                    const char* dso_name) {
  std::string* symbols = new std::string();
  if (dart_utils::ReadFileToString(symbols_path, symbols)) {
    Dart_AddSymbols(dso_name, symbols->data(), symbols->size());
  } else {
    FML_LOG(ERROR) << "Failed to load " << symbols_path;
    FML_CHECK(false);
  }
}
#endif  // !defined(DART_PRODUCT)

int main(int argc, const char** argv) {
  fx_log_init();
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

  std::unique_ptr<trace::TraceProviderWithFdio> provider;
  {
    TRACE_DURATION("dart", "CreateTraceProvider");
    bool already_started;
    // Use CreateSynchronously to prevent loss of early events.
    trace::TraceProviderWithFdio::CreateSynchronously(
        loop.dispatcher(), "dart_runner", &provider, &already_started);
  }

#if !defined(DART_PRODUCT)
#if defined(AOT_RUNTIME)
  RegisterProfilerSymbols("pkg/data/dart_aot_runner.dartprofilersymbols", "");
#else
  RegisterProfilerSymbols("pkg/data/dart_jit_runner.dartprofilersymbols", "");
#endif  // defined(AOT_RUNTIME)
#endif  // !defined(DART_PRODUCT)

  dart_utils::RunnerTemp runner_temp;
  dart_runner::DartRunner runner;
  loop.Run();
  return 0;
}
<|endoftext|>