<commit_before>#include "ioHandler.h"
#include <exception>
#include <cerrno>

void writer_helper(ReadBase *r, std::shared_ptr<OutputWriter> pe, std::shared_ptr<OutputWriter> se, bool stranded, bool no_orphans ) { //class writer
    PairedEndRead *per = dynamic_cast<PairedEndRead*>(r);
    if (per) {
        Read &one = per->non_const_read_one();
        Read &two = per->non_const_read_two();

        if (!one.getDiscard() && !two.getDiscard()) {
            pe->write(*per);
        } else if (!one.getDiscard() && !no_orphans) { // Will never be RC
            se->write_read(one, false);
        } else if (!two.getDiscard() && !no_orphans) { // if stranded RC
            se->write_read((per->get_read_two()), stranded);
        } else {

        }
    } else {
        SingleEndRead *ser = dynamic_cast<SingleEndRead*>(r);
        if (!ser) {
            throw std::runtime_error("Unknown read found");
        }
        if (! (ser->non_const_read_one()).getDiscard() ) {
            se->write(*ser);
        } else {

        }
    }
}

void skip_lr(std::istream *input) {
    while(input and input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
}

void  __attribute__ ((noreturn)) throw_error(const std::string& filename) {
    throw std::runtime_error(filename + ": " +  std::strerror( errno ));
}

int check_open_r(const std::string& filename) {
    FILE* f = NULL;

    bf::path p(filename);
    if (!bf::exists(p)) {
        throw std::runtime_error("File " + filename + " was not found.");
    }

    if (p.extension() == ".gz") {
        f = popen(("gunzip -c " + filename).c_str(), "r");
    } else {
        f = fopen(filename.c_str(), "r");
    }

    if (!f) {
        throw_error(filename);
    }
    return fileno(f);
}

int check_exists(const std::string& filename, bool force, bool gzip, bool std_out) {
    FILE* f = NULL;

    if (std_out) {
        return fileno(stdout);
    }
    std::string fname = gzip ? filename + ".gz" : filename ;

    bf::path p(fname);

    if (force || !bf::exists(p)) {
        if (gzip) {
            f = popen(("gzip > " + fname).c_str(), "w");
        } else {
            f = fopen(fname.c_str(), "w");
        }
        if (!f) {
            throw_error(fname);
        }
        return fileno(f);
    } else {
        throw std::runtime_error("File " + fname + " all ready exists. Please use -F or delete it\n");
    }
}

Read InputFastq::load_read(std::istream *input) {
    while(std::getline(*input, id) && id.size() < 1) {
    }
    if (id.size() < 1) {
        throw std::runtime_error("invalid id line empty");
    }
    if (id[0] != '@') {
        throw std::runtime_error("id line did not begin with @");
    }
    std::getline(*input, seq);
    if (seq.size() < 1) {
        throw std::runtime_error("invalid seq line empty");
    }
    std::getline(*input, id2);
    if (id2.size() < 1) {
        throw std::runtime_error("invalid id2 line empty");
    }
    if (id2[0] != '+') {
        throw std::runtime_error("invalid id2 line did not begin with +");
    }
    std::getline(*input, qual);
    if (qual.size() != seq.size()) {
        throw std::runtime_error("qual string not the same length as sequence");
    }

    // ignore extra lines at end of file
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
    return Read(seq, qual, id.substr(1));
}

Read InputFasta::load_read(std::istream *input) {
    while(std::getline(*input, id) && id.size() < 1) {
    }
    if (id.size() < 1) {
        throw std::runtime_error("invalid id - line empty");
    }
    if (id[0] != '>') {
        throw std::runtime_error("id line did not begin with >");
    }
    seq = "";
    while (std::getline(*input, tmpSeq)) {
        seq += tmpSeq;
        if (input->peek() == '>') {
            break;
        }
    }
    if (seq.size() < 1) {
        throw std::runtime_error("no sequence");
    }
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
    return Read(seq, "", id);

}

//Overrides load_read for tab delimited reads
std::vector<Read> TabReadImpl::load_read(std::istream *input) {

    std::vector <Read> reads(1);
    while(std::getline(*input, tabLine) && tabLine.size() < 1) {
    }

    std::vector <std::string> parsedRead;
    boost::split(parsedRead, tabLine, boost::is_any_of("\t"));

    if (parsedRead.size() != 3 && parsedRead.size() != 5 && parsedRead.size() != 6) {
        throw std::runtime_error("There are not either 3 (SE), 5 (PE, itab5), or 6 (PE, itab6) elements within a tab delimited file line");
    }

    if (parsedRead[1].size() != parsedRead[2].size()) {
        throw std::runtime_error("sequence and qualities are not the same length 1");
    }

    reads[0] = Read(parsedRead[1], parsedRead[2], parsedRead[0]);

    if (parsedRead.size() == 5) {

        if (parsedRead[3].size() != parsedRead[4].size()) {
            throw std::runtime_error("sequence and qualities are not the same length 2");
        }

        reads.push_back(Read(parsedRead[3], parsedRead[4], parsedRead[0]));
    }

    if (parsedRead.size() == 6) {

        if (parsedRead[4].size() != parsedRead[5].size()) {
            throw std::runtime_error("sequence and qualities are not the same length 2");
        }

        reads.push_back(Read(parsedRead[4], parsedRead[5], parsedRead[3]));
    }

    // ignore extra lines at end of file
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }

    return reads;
}

template <>
InputReader<SingleEndRead, SingleEndReadFastqImpl>::value_type InputReader<SingleEndRead, SingleEndReadFastqImpl>::next() {
    return InputReader<SingleEndRead, SingleEndReadFastqImpl>::value_type(new SingleEndRead(load_read(input)));
}

template <>
bool InputReader<SingleEndRead, SingleEndReadFastqImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(input and input->good()) and !finput.empty()){
        fs.open(check_open_r(finput.back()), bi::close_handle);
        input = &fs;
        finput.pop_back();
    }
    skip_lr(input);
    return (input and input->good());
};

template<>
InputReader<SingleEndRead, FastaReadImpl>::value_type InputReader<SingleEndRead, FastaReadImpl>::next() {
    return InputReader<SingleEndRead, FastaReadImpl>::value_type(new SingleEndRead(load_read(input)));
}

template <>
bool InputReader<SingleEndRead, FastaReadImpl>::has_next() {
    // ignore extra lines at end of file
    skip_lr(input);
    return (input and input->good());
};

template <>
InputReader<PairedEndRead, PairedEndReadFastqImpl>::value_type InputReader<PairedEndRead, PairedEndReadFastqImpl>::next() {
    Read r1 = load_read(in1);
    Read r2 = load_read(in2);
    return InputReader<PairedEndRead, PairedEndReadFastqImpl>::value_type(new PairedEndRead(r1, r2));
}

template <>
bool InputReader<PairedEndRead, PairedEndReadFastqImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(in1 and in1->good() and in2 and in2->good()) and !fin1.empty()) {
        fs1.open(check_open_r(fin1.back()), bi::never_close_handle);
        fs2.open(check_open_r(fin2.back()), bi::never_close_handle);
        in1=&fs1;
        in2=&fs2;
        fin1.pop_back();
        fin2.pop_back();
    }
    skip_lr(in1);
    skip_lr(in2);
    return (in1 and in1->good() and in2 and in2->good());
};

template<>
InputReader<PairedEndRead, InterReadImpl>::value_type InputReader<PairedEndRead, InterReadImpl>::next() {
    Read r1 = load_read(in1);
    Read r2;
    try {
        r2 = load_read(in1);
    } catch (const std::exception&) {
        throw std::runtime_error("odd number of sequences in interleaved file");
    }
    return InputReader<PairedEndRead, InterReadImpl>::value_type(new PairedEndRead(r1, r2));
}

template<>
bool InputReader<PairedEndRead, InterReadImpl>::has_next() {
    if (!(in1 and in1->good()) and !fin.empty()){
        inter.open(check_open_r(fin.back()), bi::close_handle);
        in1 = &inter;
        fin.pop_back();
    }
    skip_lr(in1);
    return(in1 && in1->good());
}

template <>
InputReader<ReadBase, TabReadImpl>::value_type InputReader<ReadBase, TabReadImpl>::next() {
    std::vector<Read> rs = load_read(in1);
    if (rs.size() == 1) {
        return InputReader<SingleEndRead, TabReadImpl>::value_type(new SingleEndRead(rs[0]));
    }
    return InputReader<PairedEndRead, TabReadImpl>::value_type(new PairedEndRead(rs[0], rs[1]));
}

template <>
bool InputReader<ReadBase, TabReadImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(in1 and in1->good()) and !fin.empty()){
        tabin.open(check_open_r(fin.back()), bi::close_handle);
        in1 = &tabin;
        fin.pop_back();
    }
    skip_lr(in1);
    return (in1 and in1->good());
}
<commit_msg>fix for allowing spaces in SuperDeduper with fastq.gz files<commit_after>#include "ioHandler.h"
#include <exception>
#include <cerrno>

void writer_helper(ReadBase *r, std::shared_ptr<OutputWriter> pe, std::shared_ptr<OutputWriter> se, bool stranded, bool no_orphans ) { //class writer
    PairedEndRead *per = dynamic_cast<PairedEndRead*>(r);
    if (per) {
        Read &one = per->non_const_read_one();
        Read &two = per->non_const_read_two();

        if (!one.getDiscard() && !two.getDiscard()) {
            pe->write(*per);
        } else if (!one.getDiscard() && !no_orphans) { // Will never be RC
            se->write_read(one, false);
        } else if (!two.getDiscard() && !no_orphans) { // if stranded RC
            se->write_read((per->get_read_two()), stranded);
        } else {

        }
    } else {
        SingleEndRead *ser = dynamic_cast<SingleEndRead*>(r);
        if (!ser) {
            throw std::runtime_error("Unknown read found");
        }
        if (! (ser->non_const_read_one()).getDiscard() ) {
            se->write(*ser);
        } else {

        }
    }
}

void skip_lr(std::istream *input) {
    while(input and input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
}

void  __attribute__ ((noreturn)) throw_error(const std::string& filename) {
    throw std::runtime_error(filename + ": " +  std::strerror( errno ));
}

int check_open_r(const std::string& filename) {
    FILE* f = NULL;

    bf::path p(filename);
    if (!bf::exists(p)) {
        throw std::runtime_error("File " + filename + " was not found.");
    }

    if (p.extension() == ".gz") {
        f = popen(("gunzip -c '" + filename + "'").c_str(), "r");
    } else {
        f = fopen(filename.c_str(), "r");
    }

    if (!f) {
        throw_error(filename);
    }
    return fileno(f);
}

int check_exists(const std::string& filename, bool force, bool gzip, bool std_out) {
    FILE* f = NULL;

    if (std_out) {
        return fileno(stdout);
    }
    std::string fname = gzip ? filename + ".gz" : filename ;

    bf::path p(fname);

    if (force || !bf::exists(p)) {
        if (gzip) {
            f = popen(("gzip > '" + fname + "'").c_str(), "w");
        } else {
            f = fopen(fname.c_str(), "w");
        }
        if (!f) {
            throw_error(fname);
        }
        return fileno(f);
    } else {
        throw std::runtime_error("File " + fname + " all ready exists. Please use -F or delete it\n");
    }
}

Read InputFastq::load_read(std::istream *input) {
    while(std::getline(*input, id) && id.size() < 1) {
    }
    if (id.size() < 1) {
        throw std::runtime_error("invalid id line empty");
    }
    if (id[0] != '@') {
        throw std::runtime_error("id line did not begin with @");
    }
    std::getline(*input, seq);
    if (seq.size() < 1) {
        throw std::runtime_error("invalid seq line empty");
    }
    std::getline(*input, id2);
    if (id2.size() < 1) {
        throw std::runtime_error("invalid id2 line empty");
    }
    if (id2[0] != '+') {
        throw std::runtime_error("invalid id2 line did not begin with +");
    }
    std::getline(*input, qual);
    if (qual.size() != seq.size()) {
        throw std::runtime_error("qual string not the same length as sequence");
    }

    // ignore extra lines at end of file
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
    return Read(seq, qual, id.substr(1));
}

Read InputFasta::load_read(std::istream *input) {
    while(std::getline(*input, id) && id.size() < 1) {
    }
    if (id.size() < 1) {
        throw std::runtime_error("invalid id - line empty");
    }
    if (id[0] != '>') {
        throw std::runtime_error("id line did not begin with >");
    }
    seq = "";
    while (std::getline(*input, tmpSeq)) {
        seq += tmpSeq;
        if (input->peek() == '>') {
            break;
        }
    }
    if (seq.size() < 1) {
        throw std::runtime_error("no sequence");
    }
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }
    return Read(seq, "", id);

}

//Overrides load_read for tab delimited reads
std::vector<Read> TabReadImpl::load_read(std::istream *input) {

    std::vector <Read> reads(1);
    while(std::getline(*input, tabLine) && tabLine.size() < 1) {
    }

    std::vector <std::string> parsedRead;
    boost::split(parsedRead, tabLine, boost::is_any_of("\t"));

    if (parsedRead.size() != 3 && parsedRead.size() != 5 && parsedRead.size() != 6) {
        throw std::runtime_error("There are not either 3 (SE), 5 (PE, itab5), or 6 (PE, itab6) elements within a tab delimited file line");
    }

    if (parsedRead[1].size() != parsedRead[2].size()) {
        throw std::runtime_error("sequence and qualities are not the same length 1");
    }

    reads[0] = Read(parsedRead[1], parsedRead[2], parsedRead[0]);

    if (parsedRead.size() == 5) {

        if (parsedRead[3].size() != parsedRead[4].size()) {
            throw std::runtime_error("sequence and qualities are not the same length 2");
        }

        reads.push_back(Read(parsedRead[3], parsedRead[4], parsedRead[0]));
    }

    if (parsedRead.size() == 6) {

        if (parsedRead[4].size() != parsedRead[5].size()) {
            throw std::runtime_error("sequence and qualities are not the same length 2");
        }

        reads.push_back(Read(parsedRead[4], parsedRead[5], parsedRead[3]));
    }

    // ignore extra lines at end of file
    while(input->good() and (input->peek() == '\n' || input->peek() == '\r')) {
        input->get();
    }

    return reads;
}

template <>
InputReader<SingleEndRead, SingleEndReadFastqImpl>::value_type InputReader<SingleEndRead, SingleEndReadFastqImpl>::next() {
    return InputReader<SingleEndRead, SingleEndReadFastqImpl>::value_type(new SingleEndRead(load_read(input)));
}

template <>
bool InputReader<SingleEndRead, SingleEndReadFastqImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(input and input->good()) and !finput.empty()){
        fs.open(check_open_r(finput.back()), bi::close_handle);
        input = &fs;
        finput.pop_back();
    }
    skip_lr(input);
    return (input and input->good());
};

template<>
InputReader<SingleEndRead, FastaReadImpl>::value_type InputReader<SingleEndRead, FastaReadImpl>::next() {
    return InputReader<SingleEndRead, FastaReadImpl>::value_type(new SingleEndRead(load_read(input)));
}

template <>
bool InputReader<SingleEndRead, FastaReadImpl>::has_next() {
    // ignore extra lines at end of file
    skip_lr(input);
    return (input and input->good());
};

template <>
InputReader<PairedEndRead, PairedEndReadFastqImpl>::value_type InputReader<PairedEndRead, PairedEndReadFastqImpl>::next() {
    Read r1 = load_read(in1);
    Read r2 = load_read(in2);
    return InputReader<PairedEndRead, PairedEndReadFastqImpl>::value_type(new PairedEndRead(r1, r2));
}

template <>
bool InputReader<PairedEndRead, PairedEndReadFastqImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(in1 and in1->good() and in2 and in2->good()) and !fin1.empty()) {
        fs1.open(check_open_r(fin1.back()), bi::never_close_handle);
        fs2.open(check_open_r(fin2.back()), bi::never_close_handle);
        in1=&fs1;
        in2=&fs2;
        fin1.pop_back();
        fin2.pop_back();
    }
    skip_lr(in1);
    skip_lr(in2);
    return (in1 and in1->good() and in2 and in2->good());
};

template<>
InputReader<PairedEndRead, InterReadImpl>::value_type InputReader<PairedEndRead, InterReadImpl>::next() {
    Read r1 = load_read(in1);
    Read r2;
    try {
        r2 = load_read(in1);
    } catch (const std::exception&) {
        throw std::runtime_error("odd number of sequences in interleaved file");
    }
    return InputReader<PairedEndRead, InterReadImpl>::value_type(new PairedEndRead(r1, r2));
}

template<>
bool InputReader<PairedEndRead, InterReadImpl>::has_next() {
    if (!(in1 and in1->good()) and !fin.empty()){
        inter.open(check_open_r(fin.back()), bi::close_handle);
        in1 = &inter;
        fin.pop_back();
    }
    skip_lr(in1);
    return(in1 && in1->good());
}

template <>
InputReader<ReadBase, TabReadImpl>::value_type InputReader<ReadBase, TabReadImpl>::next() {
    std::vector<Read> rs = load_read(in1);
    if (rs.size() == 1) {
        return InputReader<SingleEndRead, TabReadImpl>::value_type(new SingleEndRead(rs[0]));
    }
    return InputReader<PairedEndRead, TabReadImpl>::value_type(new PairedEndRead(rs[0], rs[1]));
}

template <>
bool InputReader<ReadBase, TabReadImpl>::has_next() {
    // ignore extra lines at end of file
    if (!(in1 and in1->good()) and !fin.empty()){
        tabin.open(check_open_r(fin.back()), bi::close_handle);
        in1 = &tabin;
        fin.pop_back();
    }
    skip_lr(in1);
    return (in1 and in1->good());
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2017 Bruno Ribeiro
 *
 * 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 <cursed/Window.hh>
#include <cursed/Application.hh>
#include <ncursesw/curses.h>

namespace cursed {

Application::Application() : theme()
{
	initialize();
}

Application::Application(
	const Theme &theme )
{
	initialize(&theme);
}

void Application::refresh()
{
	wnoutrefresh(stdscr);
}

void Application::initialize(
	const Theme *theme )
{
	this->state = APS_STOPPED;
	this->activeWindow = 0;
	this->theme = theme;

	initscr();

	if (!hasCapability("cup"))
	{
		endwin();
		throw 0;
	}

	if (theme == NULL)
		this->theme = &getDefaultTheme();

	applyTheme(*this->theme);

	// set background color
	wbkgd(stdscr, COLOR_PAIR(THEME_BACKGROUND));

	// disable input echo and line buffering
	noecho();
	cbreak();
	// enable keyboard translation (to be able to get all keys)
	keypad(stdscr, TRUE);
	// hide cursor
	curs_set(0);
}

void Application::applyTheme(
	const Theme &theme )
{
	if (has_colors() == TRUE)
	{
		start_color();

		// we need color redefinition and at least 32 colors for full compatibility
		bool isLimited = (hasCapability("ccc") == false) || (COLORS <= (short) FillColor::Custom4);

		if (!isLimited)
		{
			if (theme.palette != nullptr)
			{
				// set the color palette
				for (short i = 0; i == theme.palette[i].color; ++i)
				{
					init_color( (short) theme.palette[i].color,
						(short) (theme.palette[i].r * 3.9F),
						(short) (theme.palette[i].g * 3.9F),
						(short) (theme.palette[i].b * 3.9F));
				}
			}
			else
			{
				// use the original darker colors as fill colors
				for (short i = (short) TextColor::Black; i < (short) TextColor::DarkGray; ++i)
				{
					short r, g, b;
					color_content(i, &r, &g, &b);
					init_color((short)(i + (short)FillColor::Black), r, g, b);
				}
			}
		}

		// create the color pairs
		if (theme.scheme != NULL && theme.styles != NULL)
		{
			for (int i = 0; i == theme.scheme[i].index && i == theme.styles[i].index; ++i)
			{
				short textColor = (short) theme.scheme[i].foreground;
				short fillColor = (short) theme.scheme[i].background;

				// limit the amount of colors to 8 if the terminal doesn't support
				// at least 32 colors and color redefinition
				if (isLimited)
				{
					fillColor = (short) (fillColor - (short) FillColor::Black);
					if (fillColor >= (short) TextColor::Custom1)
						fillColor = 0;

					if (textColor >= (short) TextColor::Custom1)
						textColor = 0;
					if (textColor >= (short) TextColor::DarkGray)
						textColor = (short) (textColor - (short) TextColor::DarkGray);
					}

				init_pair(theme.scheme[i].index, textColor, fillColor);
			}
		}
	}
}

Application::~Application()
{
	wbkgd(stdscr, COLOR_PAIR(0));
	wclear(stdscr);
	refresh();
	endwin();
}

int Application::run(
	Window &window )
{
	return window.showModal();
}

const Theme &Application::getTheme() const
{
	return *theme;
}

bool Application::hasCapability(
	const std::string &capname )
{
	return !( (ssize_t)tigetstr(capname.c_str()) <= (ssize_t)0 ) ||
		(tigetflag(capname.c_str()) != 0);
}

bool Application::onKeyPress(
	const KeyEvent &event )
{
	// windows always handle TAB key
	if (event.key == -9)
	{
		++activeWindow;
		if (activeWindow >= (int) windows.size()) activeWindow = 0;

		return true;
	}

	// send the key event to the active control
	bool handled = false;
	handled = windows[activeWindow]->onKeyPress(event);

	if (handled == false)
	{
		// do additional key handling
	}

	return handled;
}

int Application::screenWidth() const
{
	int h, w;
	getmaxyx(stdscr, h, w);
	(void) h;
	return w;
}

int Application::screenHeight() const
{
	int h, w;
	getmaxyx(stdscr, h, w);
	return h;
}

} // namespace cursed<commit_msg>Fix 'tigetstr' and 'tigetflag' argument<commit_after>/*
 *  Copyright 2017 Bruno Ribeiro
 *
 * 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 <cursed/Window.hh>
#include <cursed/Application.hh>
#include <ncursesw/curses.h>

namespace cursed {

Application::Application() : theme()
{
	initialize();
}

Application::Application(
	const Theme &theme )
{
	initialize(&theme);
}

void Application::refresh()
{
	wnoutrefresh(stdscr);
}

void Application::initialize(
	const Theme *theme )
{
	this->state = APS_STOPPED;
	this->activeWindow = 0;
	this->theme = theme;

	initscr();

	if (!hasCapability("cup"))
	{
		endwin();
		throw 0;
	}

	if (theme == NULL)
		this->theme = &getDefaultTheme();

	applyTheme(*this->theme);

	// set background color
	wbkgd(stdscr, COLOR_PAIR(THEME_BACKGROUND));

	// disable input echo and line buffering
	noecho();
	cbreak();
	// enable keyboard translation (to be able to get all keys)
	keypad(stdscr, TRUE);
	// hide cursor
	curs_set(0);
}

void Application::applyTheme(
	const Theme &theme )
{
	if (has_colors() == TRUE)
	{
		start_color();

		// we need color redefinition and at least 32 colors for full compatibility
		bool isLimited = (hasCapability("ccc") == false) || (COLORS <= (short) FillColor::Custom4);

		if (!isLimited)
		{
			if (theme.palette != nullptr)
			{
				// set the color palette
				for (short i = 0; i == theme.palette[i].color; ++i)
				{
					init_color( (short) theme.palette[i].color,
						(short) (theme.palette[i].r * 3.9F),
						(short) (theme.palette[i].g * 3.9F),
						(short) (theme.palette[i].b * 3.9F));
				}
			}
			else
			{
				// use the original darker colors as fill colors
				for (short i = (short) TextColor::Black; i < (short) TextColor::DarkGray; ++i)
				{
					short r, g, b;
					color_content(i, &r, &g, &b);
					init_color((short)(i + (short)FillColor::Black), r, g, b);
				}
			}
		}

		// create the color pairs
		if (theme.scheme != NULL && theme.styles != NULL)
		{
			for (int i = 0; i == theme.scheme[i].index && i == theme.styles[i].index; ++i)
			{
				short textColor = (short) theme.scheme[i].foreground;
				short fillColor = (short) theme.scheme[i].background;

				// limit the amount of colors to 8 if the terminal doesn't support
				// at least 32 colors and color redefinition
				if (isLimited)
				{
					fillColor = (short) (fillColor - (short) FillColor::Black);
					if (fillColor >= (short) TextColor::Custom1)
						fillColor = 0;

					if (textColor >= (short) TextColor::Custom1)
						textColor = 0;
					if (textColor >= (short) TextColor::DarkGray)
						textColor = (short) (textColor - (short) TextColor::DarkGray);
					}

				init_pair(theme.scheme[i].index, textColor, fillColor);
			}
		}
	}
}

Application::~Application()
{
	wbkgd(stdscr, COLOR_PAIR(0));
	wclear(stdscr);
	refresh();
	endwin();
}

int Application::run(
	Window &window )
{
	return window.showModal();
}

const Theme &Application::getTheme() const
{
	return *theme;
}

bool Application::hasCapability(
	const std::string &capname )
{
	return !( (ssize_t)tigetstr((char*)capname.c_str()) <= (ssize_t)0 ) ||
		(tigetflag((char*)capname.c_str()) != 0);
}

bool Application::onKeyPress(
	const KeyEvent &event )
{
	// windows always handle TAB key
	if (event.key == -9)
	{
		++activeWindow;
		if (activeWindow >= (int) windows.size()) activeWindow = 0;

		return true;
	}

	// send the key event to the active control
	bool handled = false;
	handled = windows[activeWindow]->onKeyPress(event);

	if (handled == false)
	{
		// do additional key handling
	}

	return handled;
}

int Application::screenWidth() const
{
	int h, w;
	getmaxyx(stdscr, h, w);
	(void) h;
	return w;
}

int Application::screenHeight() const
{
	int h, w;
	getmaxyx(stdscr, h, w);
	return h;
}

} // namespace cursed<|endoftext|>


<commit_before><commit_msg>Execute the precommand even if there is no mail.<commit_after><|endoftext|>


<commit_before>// RUN: %check_clang_tidy %s readability-const-return-type %t -- -- -isystem

//  p# = positive test
//  n# = negative test

#include <type_traits>

const int p1() {
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness
// CHECK-FIXES: int p1() {
  return 1;
}

const int p15();
// CHECK-FIXES: int p15();

template <typename T>
const int p31(T v) { return 2; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p31(T v) { return 2; }

// We detect const-ness even without instantiating T.
template <typename T>
const T p32(T t) { return t; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const T' is 'const'-qual
// CHECK-FIXES: T p32(T t) { return t; }

// However, if the return type is itself a template instantiation, Clang does
// not consider it const-qualified without knowing `T`.
template <typename T>
typename std::add_const<T>::type n15(T v) { return v; }

template <typename A>
class Klazz {
public:
  Klazz(A) {}
};

class Clazz {
 public:
  Clazz *const p2() {
    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'Clazz *const' is 'co
    // CHECK-FIXES: Clazz *p2() {
    return this;
  }

  Clazz *const p3();
  // CHECK-FIXES: Clazz *p3();

  const int p4() const {
    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const
    // CHECK-FIXES: int p4() const {
    return 4;
  }

  const Klazz<const int>* const p5() const;
  // CHECK-FIXES: const Klazz<const int>* p5() const;

  const Clazz operator++(int x) {  //  p12
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz' is 'const
  // CHECK-FIXES: Clazz operator++(int x) {
  }

  struct Strukt {
    int i;
  };

  const Strukt p6() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
  // CHECK-FIXES: Strukt p6() {}

  // No warning is emitted here, because this is only the declaration.  The
  // warning will be associated with the definition, below.
  const Strukt* const p7();
  // CHECK-FIXES: const Strukt* p7();

  // const-qualifier is the first `const` token, but not the first token.
  static const int p8() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const'-
  // CHECK-FIXES: static int p8() {}

  static const Strukt p9() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
  // CHECK-FIXES: static Strukt p9() {}

  int n0() const { return 0; }
  const Klazz<const int>& n11(const Klazz<const int>) const;
};

Clazz *const Clazz::p3() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
  // CHECK-FIXES: Clazz *Clazz::p3() {
  return this;
}

const Klazz<const int>* const Clazz::p5() const {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
// CHECK-FIXES: const Klazz<const int>* Clazz::p5() const {}

const Clazz::Strukt* const Clazz::p7() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz::Strukt *con
// CHECK-FIXES: const Clazz::Strukt* Clazz::p7() {}

Clazz *const p10();
// CHECK-FIXES: Clazz *p10();

Clazz *const p10() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
  // CHECK-FIXES: Clazz *p10() {
  return new Clazz();
}

const Clazz bar;
const Clazz *const p11() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz *const' is
  // CHECK-FIXES: const Clazz *p11() {
  return &bar;
}

const Klazz<const int> p12() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int>'
// CHECK-FIXES: Klazz<const int> p12() {}

const Klazz<const int>* const p13() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
// CHECK-FIXES: const Klazz<const int>* p13() {}

// re-declaration of p15.
const int p15();
// CHECK-FIXES: int p15();

const int p15() {
// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
// CHECK-FIXES: int p15() {
  return 0;
}

// Exercise the lexer.

const /* comment */ /* another comment*/ int p16() { return 0; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
// CHECK-FIXES: /* comment */ /* another comment*/ int p16() { return 0; }

/* comment */ const
// CHECK-MESSAGES: [[@LINE-1]]:15: warning:
// CHECK-FIXES: /* comment */
// more
/* another comment*/ int p17() { return 0; }

// Test cases where the `const` token lexically is hidden behind some form of
// indirection.

#define CONSTINT const int
CONSTINT p18() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

#define CONST const
CONST int p19() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

using ty = const int;
ty p21() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty' (aka 'const int') is

typedef const int ty2;
ty2 p22() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty2' (aka 'const int') i

// Declaration uses a macro, while definition doesn't.  In this case, we won't
// fix the declaration, and will instead issue a warning.
CONST int p23();
// CHECK-NOTE: [[@LINE-1]]:1: note: could not transform this declaration

const int p23();
// CHECK-FIXES: int p23();

const int p23() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p23() { return 3; }

int const p24() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p24() { return 3; }

int const * const p25(const int* p) { return p; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int *const' is 'co
// CHECK-FIXES: int const * p25(const int* p) { return p; }

// We cannot (yet) fix instances that use trailing return types, but we can
// warn.
auto p26() -> const int { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
auto p27() -> int const { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

std::add_const<int>::type p28() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'std::add_const<int>::typ

// p29, p30 are based on
// llvm/projects/test-suite/SingleSource/Benchmarks/Misc-C++-EH/spirit.cpp:
template <class T>
Klazz<T const> const p29(T const &t) { return {}; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const T>' is
// CHECK-FIXES: Klazz<T const> p29(T const &t) { return {}; }

Klazz<char const *> const p30(char const *s) { return s; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const char *
// CHECK-FIXES: Klazz<char const *> p30(char const *s) { return s; }

const int n1 = 1;
const Clazz n2 = Clazz();
const Clazz* n3 = new Clazz();
Clazz *const n4 = new Clazz();
const Clazz *const n5 = new Clazz();
constexpr int n6 = 6;
constexpr int n7() { return 8; }
const int eight = 8;
constexpr const int* n8() { return &eight; }
Klazz<const int> n9();
const Klazz<const int>* n10();
const Klazz<const int>& Clazz::n11(const Klazz<const int>) const {}

// Declaration only.
const int n14();

int **const * n_multiple_ptr();
int *const & n_pointer_ref();
<commit_msg>Removing a reliance on system headers from this test; NFC.<commit_after>// RUN: %check_clang_tidy %s readability-const-return-type %t

//  p# = positive test
//  n# = negative test

namespace std {
template< class T >
struct add_cv { typedef const volatile T type; };

template< class T> struct add_const { typedef const T type; };

template< class T> struct add_volatile { typedef volatile T type; };
}

const int p1() {
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness
// CHECK-FIXES: int p1() {
  return 1;
}

const int p15();
// CHECK-FIXES: int p15();

template <typename T>
const int p31(T v) { return 2; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p31(T v) { return 2; }

// We detect const-ness even without instantiating T.
template <typename T>
const T p32(T t) { return t; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const T' is 'const'-qual
// CHECK-FIXES: T p32(T t) { return t; }

// However, if the return type is itself a template instantiation, Clang does
// not consider it const-qualified without knowing `T`.
template <typename T>
typename std::add_const<T>::type n15(T v) { return v; }

template <typename A>
class Klazz {
public:
  Klazz(A) {}
};

class Clazz {
 public:
  Clazz *const p2() {
    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'Clazz *const' is 'co
    // CHECK-FIXES: Clazz *p2() {
    return this;
  }

  Clazz *const p3();
  // CHECK-FIXES: Clazz *p3();

  const int p4() const {
    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const
    // CHECK-FIXES: int p4() const {
    return 4;
  }

  const Klazz<const int>* const p5() const;
  // CHECK-FIXES: const Klazz<const int>* p5() const;

  const Clazz operator++(int x) {  //  p12
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz' is 'const
  // CHECK-FIXES: Clazz operator++(int x) {
  }

  struct Strukt {
    int i;
  };

  const Strukt p6() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
  // CHECK-FIXES: Strukt p6() {}

  // No warning is emitted here, because this is only the declaration.  The
  // warning will be associated with the definition, below.
  const Strukt* const p7();
  // CHECK-FIXES: const Strukt* p7();

  // const-qualifier is the first `const` token, but not the first token.
  static const int p8() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const'-
  // CHECK-FIXES: static int p8() {}

  static const Strukt p9() {}
  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
  // CHECK-FIXES: static Strukt p9() {}

  int n0() const { return 0; }
  const Klazz<const int>& n11(const Klazz<const int>) const;
};

Clazz *const Clazz::p3() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
  // CHECK-FIXES: Clazz *Clazz::p3() {
  return this;
}

const Klazz<const int>* const Clazz::p5() const {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
// CHECK-FIXES: const Klazz<const int>* Clazz::p5() const {}

const Clazz::Strukt* const Clazz::p7() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz::Strukt *con
// CHECK-FIXES: const Clazz::Strukt* Clazz::p7() {}

Clazz *const p10();
// CHECK-FIXES: Clazz *p10();

Clazz *const p10() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
  // CHECK-FIXES: Clazz *p10() {
  return new Clazz();
}

const Clazz bar;
const Clazz *const p11() {
  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz *const' is
  // CHECK-FIXES: const Clazz *p11() {
  return &bar;
}

const Klazz<const int> p12() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int>'
// CHECK-FIXES: Klazz<const int> p12() {}

const Klazz<const int>* const p13() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
// CHECK-FIXES: const Klazz<const int>* p13() {}

// re-declaration of p15.
const int p15();
// CHECK-FIXES: int p15();

const int p15() {
// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
// CHECK-FIXES: int p15() {
  return 0;
}

// Exercise the lexer.

const /* comment */ /* another comment*/ int p16() { return 0; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
// CHECK-FIXES: /* comment */ /* another comment*/ int p16() { return 0; }

/* comment */ const
// CHECK-MESSAGES: [[@LINE-1]]:15: warning:
// CHECK-FIXES: /* comment */
// more
/* another comment*/ int p17() { return 0; }

// Test cases where the `const` token lexically is hidden behind some form of
// indirection.

#define CONSTINT const int
CONSTINT p18() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

#define CONST const
CONST int p19() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

using ty = const int;
ty p21() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty' (aka 'const int') is

typedef const int ty2;
ty2 p22() {}
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty2' (aka 'const int') i

// Declaration uses a macro, while definition doesn't.  In this case, we won't
// fix the declaration, and will instead issue a warning.
CONST int p23();
// CHECK-NOTE: [[@LINE-1]]:1: note: could not transform this declaration

const int p23();
// CHECK-FIXES: int p23();

const int p23() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p23() { return 3; }

int const p24() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
// CHECK-FIXES: int p24() { return 3; }

int const * const p25(const int* p) { return p; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int *const' is 'co
// CHECK-FIXES: int const * p25(const int* p) { return p; }

// We cannot (yet) fix instances that use trailing return types, but we can
// warn.
auto p26() -> const int { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
auto p27() -> int const { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu

std::add_const<int>::type p28() { return 3; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'std::add_const<int>::typ

// p29, p30 are based on
// llvm/projects/test-suite/SingleSource/Benchmarks/Misc-C++-EH/spirit.cpp:
template <class T>
Klazz<T const> const p29(T const &t) { return {}; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const T>' is
// CHECK-FIXES: Klazz<T const> p29(T const &t) { return {}; }

Klazz<char const *> const p30(char const *s) { return s; }
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const char *
// CHECK-FIXES: Klazz<char const *> p30(char const *s) { return s; }

const int n1 = 1;
const Clazz n2 = Clazz();
const Clazz* n3 = new Clazz();
Clazz *const n4 = new Clazz();
const Clazz *const n5 = new Clazz();
constexpr int n6 = 6;
constexpr int n7() { return 8; }
const int eight = 8;
constexpr const int* n8() { return &eight; }
Klazz<const int> n9();
const Klazz<const int>* n10();
const Klazz<const int>& Clazz::n11(const Klazz<const int>) const {}

// Declaration only.
const int n14();

int **const * n_multiple_ptr();
int *const & n_pointer_ref();
<|endoftext|>


<commit_before>// @(#):$Id$
// Author: Andrei Gheata   01/03/11

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////
//
// TGeoBranchArray - An array of daughter indices making a geometry path.
//   Can be used to backup/restore a state. To setup an object of this type,
// one should use:
//   TGeoBranchArray *array = new TGeoBranchArray(level);
//   array->InitFromNavigator(nav); (To initialize from current navigator state)
// The navigator can be updated to reflect this path array:
//   array->UpdateNavigator();
//
/////////////////////////////////////////////////////////////////////////////

#include "TGeoBranchArray.h"

#include "TMath.h"
#include "TString.h"
#include "TGeoMatrix.h"
#include "TGeoNavigator.h"
#include "TGeoManager.h"

ClassImp(TGeoBranchArray)

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(UShort_t level)
                :fLevel(level),
                 fArray(NULL),
                 fMatrix(NULL),
                 fClient(NULL)
{
// Constructor. Alocates the array with a size given by level.
   fArray = new UShort_t[level];
}

//______________________________________________________________________________
TGeoBranchArray::~TGeoBranchArray()
{
// Destructor.
   delete [] fArray;
   delete fMatrix;
}

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray&  other)
                :TObject(other),
                 fLevel(other.fLevel),
                 fArray(NULL),
                 fMatrix(NULL)
{
// Copy constructor.
   if (fLevel) fArray = new UShort_t[fLevel];
   if (other.fMatrix) fMatrix = new TGeoHMatrix(*(other.fMatrix));
}

//______________________________________________________________________________
TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
{
// Assignment.
   if (&other == this) return *this;
   fLevel = other.fLevel;
   if (fLevel) fArray = new UShort_t[fLevel];
   if (other.fMatrix) {
      fMatrix = new TGeoHMatrix();
      fMatrix->CopyFrom(other.fMatrix);
   }
   return *this;
}

//______________________________________________________________________________
void TGeoBranchArray::AddLevel(UShort_t dindex)
{
// Add and extra daughter to the current path array. No validity check performed !
   if (!fLevel) {
      Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
      return;
   }
   fLevel++;
   UShort_t *array = new UShort_t[fLevel];
   memcpy(array, fArray, (fLevel-1)*sizeof(UShort_t));
   array[fLevel-1] = dindex;
   delete [] fArray;
   fArray = array;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value==0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
{
// Not equal operator.
   Int_t value = Compare(&other);
   if (value!=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
{
// Binary search in an array of n pointers to branch arrays, to locate value.
// Returns element index or index of nearest element smaller than value
   Long64_t nabove, nbelow, middle;
   const TGeoBranchArray *pind;
   nabove = n+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      pind = array[middle-1];
      if (*value == *pind) return middle-1;
      if (*value  < *pind) nabove = middle;
      else                          nbelow = middle;
   }
   return nbelow-1;
}

//______________________________________________________________________________
Int_t TGeoBranchArray::Compare(const TObject *obj) const
{
// Compare with other object of same type. Returns -1 if this is smaller (first
// smaller array value prevails), 0 if equal (size and values) and 1 if this is
// larger.
   UShort_t i;
   TGeoBranchArray *other = (TGeoBranchArray*)obj;
   UShort_t otherLevel = other->GetLevel();
   UShort_t maxLevel = TMath::Min(fLevel, otherLevel);
   UShort_t *otherArray = other->GetArray();
   for (i=0; i<maxLevel; i++) {
      if (fArray[i]==otherArray[i]) continue;
      if (fArray[i]<otherArray[i]) return -1;
      return 1;
   }
   if (fLevel==otherLevel) return 0;
   if (fLevel<otherLevel) return -1;
   return 1;
}

//______________________________________________________________________________
void TGeoBranchArray::CleanMatrix()
{
// Garbage collect the stored matrix.
   delete fMatrix; fMatrix = 0;
}

//______________________________________________________________________________
TGeoNode *TGeoBranchArray::GetNode(UShort_t level) const
{
   TGeoNode *node = gGeoManager->GetTopNode();
   if (!level) return node;
   if (level>fLevel) return NULL;
   for (Int_t i=0; i<level; i++) node = node->GetVolume()->GetNode(fArray[i]);
   return node;
}

//______________________________________________________________________________
void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
{
// Init the branch array from current navigator state.
   UShort_t level = (UShort_t)nav->GetLevel();
   if (!fMatrix) fMatrix = new TGeoHMatrix();
   fMatrix->CopyFrom(nav->GetCurrentMatrix());
   if (!level) {
//      delete [] fArray; fArray = 0;
      fLevel = 0;
      return;
   }
   if (!fArray || level>fLevel) {
      delete [] fArray;
      fArray = new UShort_t[level];
   }
   fLevel = level;
   TGeoNode *mother = nav->GetMother(fLevel);
   for (Int_t i=fLevel-1; i>=0; i--) {
      TGeoNode *node = nav->GetMother(i);
      Int_t index = mother->GetVolume()->GetIndex(node);
      fArray[fLevel-i-1] = index;
      mother = node;
   }
}

//______________________________________________________________________________
void TGeoBranchArray::GetPath(TString &path) const
{
// Fill path pointed by the array.
   path = "/";
   TGeoNode *node = GetNode(0);
   path += node->GetName();
   for (Int_t i=0; i<fLevel; i++) {
      path += "/";
      node = node->GetVolume()->GetNode(fArray[i]);
      path += node->GetName();
   }
}

//______________________________________________________________________________
void TGeoBranchArray::Print(Option_t *) const
{
// Print branch information
   TString path;
   GetPath(path);
   printf("branch:    %s\n", path.Data());
}

//______________________________________________________________________________
void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
{
// Sorting of an array of branch array pointers.
   for (Int_t i=0; i<n; i++) index[i] = i;
   if (down)
      std::sort(index, index + n, compareBAdesc(array));
   else
      std::sort(index, index + n, compareBAasc(array));
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
{
// Update the navigator to reflect the branch.
   nav->CdTop();
   for (Int_t i=0; i<fLevel; i++) nav->CdDown(fArray[i]);
}
<commit_msg>Coverity fix<commit_after>// @(#):$Id$
// Author: Andrei Gheata   01/03/11

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////
//
// TGeoBranchArray - An array of daughter indices making a geometry path.
//   Can be used to backup/restore a state. To setup an object of this type,
// one should use:
//   TGeoBranchArray *array = new TGeoBranchArray(level);
//   array->InitFromNavigator(nav); (To initialize from current navigator state)
// The navigator can be updated to reflect this path array:
//   array->UpdateNavigator();
//
/////////////////////////////////////////////////////////////////////////////

#include "TGeoBranchArray.h"

#include "TMath.h"
#include "TString.h"
#include "TGeoMatrix.h"
#include "TGeoNavigator.h"
#include "TGeoManager.h"

ClassImp(TGeoBranchArray)

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(UShort_t level)
                :fLevel(level),
                 fArray(NULL),
                 fMatrix(NULL),
                 fClient(NULL)
{
// Constructor. Alocates the array with a size given by level.
   fArray = new UShort_t[level];
}

//______________________________________________________________________________
TGeoBranchArray::~TGeoBranchArray()
{
// Destructor.
   delete [] fArray;
   delete fMatrix;
}

//______________________________________________________________________________
TGeoBranchArray::TGeoBranchArray(const TGeoBranchArray&  other)
                :TObject(other),
                 fLevel(other.fLevel),
                 fArray(NULL),
                 fMatrix(NULL),
                 fClient(other.fClient)
{
// Copy constructor.
   if (fLevel) fArray = new UShort_t[fLevel];
   if (other.fMatrix) fMatrix = new TGeoHMatrix(*(other.fMatrix));
}

//______________________________________________________________________________
TGeoBranchArray& TGeoBranchArray::operator=(const TGeoBranchArray& other)
{
// Assignment.
   if (&other == this) return *this;
   fLevel = other.fLevel;
   if (fLevel) fArray = new UShort_t[fLevel];
   if (other.fMatrix) {
      fMatrix = new TGeoHMatrix();
      fMatrix->CopyFrom(other.fMatrix);
   }
   fClient = other.fClient;
   return *this;
}

//______________________________________________________________________________
void TGeoBranchArray::AddLevel(UShort_t dindex)
{
// Add and extra daughter to the current path array. No validity check performed !
   if (!fLevel) {
      Error("AddLevel", "You must initialize from navigator or copy from another branch array first.");
      return;
   }
   fLevel++;
   UShort_t *array = new UShort_t[fLevel];
   memcpy(array, fArray, (fLevel-1)*sizeof(UShort_t));
   array[fLevel-1] = dindex;
   delete [] fArray;
   fArray = array;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator ==(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value==0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator !=(const TGeoBranchArray& other) const
{
// Not equal operator.
   Int_t value = Compare(&other);
   if (value!=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator >=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value>=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Bool_t TGeoBranchArray::operator <=(const TGeoBranchArray& other) const
{
// Is equal operator.
   Int_t value = Compare(&other);
   if (value<=0) return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
Long64_t TGeoBranchArray::BinarySearch(Long64_t n, const TGeoBranchArray **array, TGeoBranchArray *value)
{
// Binary search in an array of n pointers to branch arrays, to locate value.
// Returns element index or index of nearest element smaller than value
   Long64_t nabove, nbelow, middle;
   const TGeoBranchArray *pind;
   nabove = n+1;
   nbelow = 0;
   while(nabove-nbelow > 1) {
      middle = (nabove+nbelow)/2;
      pind = array[middle-1];
      if (*value == *pind) return middle-1;
      if (*value  < *pind) nabove = middle;
      else                          nbelow = middle;
   }
   return nbelow-1;
}

//______________________________________________________________________________
Int_t TGeoBranchArray::Compare(const TObject *obj) const
{
// Compare with other object of same type. Returns -1 if this is smaller (first
// smaller array value prevails), 0 if equal (size and values) and 1 if this is
// larger.
   UShort_t i;
   TGeoBranchArray *other = (TGeoBranchArray*)obj;
   UShort_t otherLevel = other->GetLevel();
   UShort_t maxLevel = TMath::Min(fLevel, otherLevel);
   UShort_t *otherArray = other->GetArray();
   for (i=0; i<maxLevel; i++) {
      if (fArray[i]==otherArray[i]) continue;
      if (fArray[i]<otherArray[i]) return -1;
      return 1;
   }
   if (fLevel==otherLevel) return 0;
   if (fLevel<otherLevel) return -1;
   return 1;
}

//______________________________________________________________________________
void TGeoBranchArray::CleanMatrix()
{
// Garbage collect the stored matrix.
   delete fMatrix; fMatrix = 0;
}

//______________________________________________________________________________
TGeoNode *TGeoBranchArray::GetNode(UShort_t level) const
{
   TGeoNode *node = gGeoManager->GetTopNode();
   if (!level) return node;
   if (level>fLevel) return NULL;
   for (Int_t i=0; i<level; i++) node = node->GetVolume()->GetNode(fArray[i]);
   return node;
}

//______________________________________________________________________________
void TGeoBranchArray::InitFromNavigator(TGeoNavigator *nav)
{
// Init the branch array from current navigator state.
   UShort_t level = (UShort_t)nav->GetLevel();
   if (!fMatrix) fMatrix = new TGeoHMatrix();
   fMatrix->CopyFrom(nav->GetCurrentMatrix());
   if (!level) {
//      delete [] fArray; fArray = 0;
      fLevel = 0;
      return;
   }
   if (!fArray || level>fLevel) {
      delete [] fArray;
      fArray = new UShort_t[level];
   }
   fLevel = level;
   TGeoNode *mother = nav->GetMother(fLevel);
   for (Int_t i=fLevel-1; i>=0; i--) {
      TGeoNode *node = nav->GetMother(i);
      Int_t index = mother->GetVolume()->GetIndex(node);
      fArray[fLevel-i-1] = index;
      mother = node;
   }
}

//______________________________________________________________________________
void TGeoBranchArray::GetPath(TString &path) const
{
// Fill path pointed by the array.
   path = "/";
   TGeoNode *node = GetNode(0);
   path += node->GetName();
   for (Int_t i=0; i<fLevel; i++) {
      path += "/";
      node = node->GetVolume()->GetNode(fArray[i]);
      path += node->GetName();
   }
}

//______________________________________________________________________________
void TGeoBranchArray::Print(Option_t *) const
{
// Print branch information
   TString path;
   GetPath(path);
   printf("branch:    %s\n", path.Data());
}

//______________________________________________________________________________
void TGeoBranchArray::Sort(Int_t n, TGeoBranchArray **array, Int_t *index, Bool_t down)
{
// Sorting of an array of branch array pointers.
   for (Int_t i=0; i<n; i++) index[i] = i;
   if (down)
      std::sort(index, index + n, compareBAdesc(array));
   else
      std::sort(index, index + n, compareBAasc(array));
}

//______________________________________________________________________________
void TGeoBranchArray::UpdateNavigator(TGeoNavigator *nav) const
{
// Update the navigator to reflect the branch.
   nav->CdTop();
   for (Int_t i=0; i<fLevel; i++) nav->CdDown(fArray[i]);
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include "pkcs11test.h"

using namespace std;  // So sue me

TEST_F(PKCS11Test, EnumerateSlots) {
  // First determine how many slots.
  CK_ULONG slot_count;
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, &slot_count));
  unique_ptr<CK_SLOT_ID, freer> slot((CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID)));
  // Retrieve slot list.
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, slot.get(), &slot_count));
  for (int ii = 0; ii < slot_count; ii++) {
    CK_SLOT_INFO slot_info = {0};
    EXPECT_CKR_OK(g_fns->C_GetSlotInfo(slot.get()[ii], &slot_info));
    cout << "slot[" << ii << "] = " << (unsigned int)slot.get()[ii] << " = " << slot_description(&slot_info) << endl;
    if (slot_info.flags & CKF_TOKEN_PRESENT) {
      CK_TOKEN_INFO token = {0};
      EXPECT_CKR_OK(g_fns->C_GetTokenInfo(slot.get()[ii], &token));
      cout << "  " << token_description(&token) << endl;
    }
  }
}

TEST_F(PKCS11Test, EnumerateMechanisms) {
  CK_ULONG mechanism_count;
  EXPECT_CKR_OK(g_fns->C_GetMechanismList(g_slot_id, NULL_PTR, &mechanism_count));
  unique_ptr<CK_MECHANISM_TYPE, freer> mechanism((CK_MECHANISM_TYPE_PTR)malloc(mechanism_count * sizeof(CK_MECHANISM_TYPE)));
  EXPECT_CKR_OK(g_fns->C_GetMechanismList(g_slot_id, mechanism.get(), &mechanism_count));
  for (int ii = 0; ii < mechanism_count; ii++) {
    CK_MECHANISM_INFO mechanism_info;
    EXPECT_CKR_OK(g_fns->C_GetMechanismInfo(g_slot_id, mechanism.get()[ii], &mechanism_info));
    cout << "mechanism[" << ii << "]=" << mechanism_type_name(mechanism.get()[ii]) << mechanism_info_description(&mechanism_info) << endl;
  }
}
<commit_msg>Add more slot/mechanism tests<commit_after>// Tests to cover slot and token management functions (PKCS#11 s11.5):
//   C_GetSlotList
//   C_GetSlotInfo
//   C_GetTokenInfo
//   C_WaitForSlotEvent
//   C_GetMechanismList
//   C_GetMechanismInfo
//   C_InitToken
//   C_InitPIN
//   C_SetPIN

#include <cstdlib>
#include "pkcs11test.h"

using namespace std;  // So sue me

TEST_F(PKCS11Test, EnumerateSlots) {
  // First determine how many slots.
  CK_ULONG slot_count;
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, &slot_count));
  unique_ptr<CK_SLOT_ID, freer> slot((CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID)));
  // Retrieve slot list.
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, slot.get(), &slot_count));
  for (int ii = 0; ii < slot_count; ii++) {
    CK_SLOT_INFO slot_info = {0};
    EXPECT_CKR_OK(g_fns->C_GetSlotInfo(slot.get()[ii], &slot_info));
    cout << "slot[" << ii << "] = " << (unsigned int)slot.get()[ii] << " = " << slot_description(&slot_info) << endl;
    if (slot_info.flags & CKF_TOKEN_PRESENT) {
      CK_TOKEN_INFO token_info = {0};
      EXPECT_CKR_OK(g_fns->C_GetTokenInfo(slot.get()[ii], &token_info));
      cout << "  " << token_description(&token_info) << endl;
    }
  }
}

TEST_F(PKCS11Test, EnumerateMechanisms) {
  CK_ULONG mechanism_count;
  EXPECT_CKR_OK(g_fns->C_GetMechanismList(g_slot_id, NULL_PTR, &mechanism_count));
  unique_ptr<CK_MECHANISM_TYPE, freer> mechanism((CK_MECHANISM_TYPE_PTR)malloc(mechanism_count * sizeof(CK_MECHANISM_TYPE)));
  EXPECT_CKR_OK(g_fns->C_GetMechanismList(g_slot_id, mechanism.get(), &mechanism_count));
  for (int ii = 0; ii < mechanism_count; ii++) {
    CK_MECHANISM_INFO mechanism_info;
    EXPECT_CKR_OK(g_fns->C_GetMechanismInfo(g_slot_id, mechanism.get()[ii], &mechanism_info));
    cout << "mechanism[" << ii << "]=" << mechanism_type_name(mechanism.get()[ii]) << " " << mechanism_info_description(&mechanism_info) << endl;
  }
}

TEST_F(PKCS11Test, GetSlotList) {
  CK_ULONG slot_count;
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, &slot_count));
  unique_ptr<CK_SLOT_ID, freer> all_slots((CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID)));
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, all_slots.get(), &slot_count));
  set<CK_SLOT_ID> all_slots_set;
  for (int ii = 0; ii < slot_count; ++ii) all_slots_set.insert(all_slots.get()[ii]);

  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_TRUE, NULL_PTR, &slot_count));
  unique_ptr<CK_SLOT_ID, freer> token_slots((CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID)));
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_TRUE, token_slots.get(), &slot_count));

  // Every slot with a token should appear in the list of all slots.
  for (int ii = 0; ii < slot_count; ++ii) {
    EXPECT_EQ(1, all_slots_set.count(token_slots.get()[ii]));
  }
}

TEST_F(PKCS11Test, GetSlotListFailTooSmall) {
  CK_ULONG slot_count;
  EXPECT_CKR_OK(g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, &slot_count));
  if (slot_count > 1) {
    unique_ptr<CK_SLOT_ID, freer> all_slots((CK_SLOT_ID*)malloc(slot_count * sizeof(CK_SLOT_ID)));
    CK_ULONG new_slot_count = (slot_count - 1);
    EXPECT_CKR(CKR_BUFFER_TOO_SMALL, g_fns->C_GetSlotList(CK_FALSE, all_slots.get(), &new_slot_count));
    EXPECT_EQ(slot_count, new_slot_count);
  }
}

TEST_F(PKCS11Test, GetSlotListFailArgumentsBad) {
  // TODO(drysdale): reinstate (dumps core on OpenCryptoKi)
  // EXPECT_CKR(CKR_ARGUMENTS_BAD, g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, NULL_PTR));
}

TEST_F(PKCS11Test, GetSlotInfoFail) {
  CK_SLOT_INFO slot_info = {0};
  EXPECT_CKR(CKR_SLOT_ID_INVALID, g_fns->C_GetSlotInfo(123456, &slot_info));
  EXPECT_CKR(CKR_FUNCTION_FAILED, g_fns->C_GetSlotInfo(g_slot_id, nullptr));
}

TEST_F(PKCS11Test, GetTokenInfoFail) {
  CK_TOKEN_INFO token_info = {0};
  EXPECT_CKR(CKR_SLOT_ID_INVALID, g_fns->C_GetTokenInfo(123456, &token_info));
  EXPECT_CKR(CKR_ARGUMENTS_BAD, g_fns->C_GetTokenInfo(g_slot_id, nullptr));
}

TEST_F(PKCS11Test, WaitForSlotEvent) {
  CK_SLOT_ID slot_id = -1;
  // Ask twice without blocking, to clear any pending event.
  g_fns->C_WaitForSlotEvent(CKF_DONT_BLOCK, &slot_id, NULL_PTR);
  EXPECT_CKR(CKR_NO_EVENT, g_fns->C_WaitForSlotEvent(CKF_DONT_BLOCK, &slot_id, NULL_PTR));
}

TEST_F(PKCS11Test, GetMechanismListFailTooSmall) {
  CK_ULONG mechanism_count;
  EXPECT_CKR_OK(g_fns->C_GetMechanismList(g_slot_id, NULL_PTR, &mechanism_count));
  if (mechanism_count > 1) {
    unique_ptr<CK_MECHANISM_TYPE, freer> mechanism((CK_MECHANISM_TYPE_PTR)malloc(mechanism_count * sizeof(CK_MECHANISM_TYPE)));
    CK_ULONG new_mechanism_count = mechanism_count - 1;
    EXPECT_CKR(CKR_BUFFER_TOO_SMALL, g_fns->C_GetMechanismList(g_slot_id, mechanism.get(), &new_mechanism_count));
    EXPECT_EQ(mechanism_count, new_mechanism_count);
  }
}

TEST_F(PKCS11Test, GetMechanismInfoInvalid) {
  CK_MECHANISM_INFO mechanism_info;
  EXPECT_CKR(CKR_MECHANISM_INVALID, g_fns->C_GetMechanismInfo(g_slot_id, CKM_VENDOR_DEFINED + 1, &mechanism_info));
}

TEST_F(PKCS11Test, GetMechanismInfoFail) {
  EXPECT_CKR(CKR_FUNCTION_FAILED, g_fns->C_GetMechanismInfo(g_slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR));
}

TEST(Slot, NoInit) {
  // Check nothing works if C_Initialize has not been called.
  CK_ULONG slot_count;
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_GetSlotList(CK_FALSE, NULL_PTR, &slot_count));
  CK_SLOT_INFO slot_info = {0};
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_GetSlotInfo(g_slot_id, &slot_info));
  CK_TOKEN_INFO token_info = {0};
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_GetTokenInfo(g_slot_id, &token_info));
  CK_SLOT_ID slot_id = -1;
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_WaitForSlotEvent(CKF_DONT_BLOCK, &slot_id, NULL_PTR));
  CK_ULONG mechanism_count;
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_GetMechanismList(g_slot_id, NULL_PTR, &mechanism_count));
  CK_MECHANISM_INFO mechanism_info;
  EXPECT_CKR(CKR_CRYPTOKI_NOT_INITIALIZED, g_fns->C_GetMechanismInfo(g_slot_id, CKM_RSA_PKCS_KEY_PAIR_GEN, &mechanism_info));
  // TODO(drysdale): Add C_InitToken, C_InitPIN, C_SetPIN
}
<|endoftext|>


<commit_before>// Helper classes for writing unittests testing the entire asynchronous
// stack. Allows to send incoming messages (in gridconnect format) and set
// expectations on messages produced.
//
// Only include this file in unittests.

#ifndef _UTILS_ASYNC_IF_TEST_HELPER_HXX_
#define _UTILS_ASYNC_IF_TEST_HELPER_HXX_

#include "nmranet/AliasAllocator.hxx"
#include "nmranet/IfCan.hxx"
#include "nmranet/EventService.hxx"
#include "nmranet/DefaultNode.hxx"
#include "nmranet_config.h"
#include "utils/GridConnectHub.hxx"
#include "utils/test_main.hxx"

using ::testing::AtLeast;
using ::testing::AtMost;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Invoke;
using ::testing::IsNull;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::StrCaseEq;
using ::testing::StrictMock;
using ::testing::WithArg;
using ::testing::_;

class TrainTestHelper;

///@todo(balazs.racz) remove
// void (*g_invoke)(Notifiable *) = &InvokeNotification;

HubFlow gc_hub0(&g_service);
CanHubFlow can_hub0(&g_service);
GCAdapterBase *g_gc_adapter = nullptr;

HubFlow gc_hub1(&g_service);
CanHubFlow can_hub1(&g_service);
GCAdapterBase *g_gc_adapter1 = nullptr;

/** Helper class for setting expectation on the CANbus traffic in unit
 * tests. */
class MockSend : public HubPort
{
public:
    MockSend()
        : HubPort(&g_service)
    {
    }

    MOCK_METHOD1(mwrite, void(const string &s));

    virtual Action entry()
    {
        string s(message()->data()->data(), message()->data()->size());
        mwrite(s);
        return release_and_exit();
    }
};

void InvokeNotification(Notifiable *done)
{
    done->notify();
}

static void print_packet(const string &pkt)
{
    fprintf(stderr, "%s\n", pkt.c_str());
}

class AsyncCanTest : public testing::Test
{
public:
    static void SetUpTestCase()
    {
        g_gc_adapter =
            GCAdapterBase::CreateGridConnectAdapter(&gc_hub0, &can_hub0, false);
    }

    static void TearDownTestCase()
    {
        delete g_gc_adapter;
    }

protected:
    AsyncCanTest()
    {
        gc_hub0.register_port(&canBus_);
    }

    ~AsyncCanTest()
    {
        gc_hub0.unregister_port(&canBus_);
        if (printer_.get())
        {
            gc_hub0.unregister_port(printer_.get());
        }
    }

    /** Delays the current thread until we are certain that all asynchrnous
        processing has completed. */
    void wait()
    {
        wait_for_main_executor();
    }

/** Adds an expectation that the code will send a packet to the CANbus.

    Example:
    expect_packet(":X1954412DN05010101FFFF0000;");

    @param gc_packet the packet in GridConnect format, including the leading
    : and trailing ;
*/
#define expect_packet(gc_packet)                                               \
    EXPECT_CALL(canBus_, mwrite(StrCaseEq(gc_packet)))

    /** Ignores all produced packets.
     *
     *  Tihs can be used in tests where the expectations are tested in a higher
     *  level than monitoring the CANbus traffic.
    */
    void expect_any_packet()
    {
        EXPECT_CALL(canBus_, mwrite(_)).Times(AtLeast(0)).WillRepeatedly(
            WithArg<0>(Invoke(print_packet)));
    }

    /** Prints all packets sent to the canbus until the end of the current test
     * function.
    */
    void print_all_packets()
    {
        NiceMock<MockSend> *m = new NiceMock<MockSend>();
        EXPECT_CALL(*m, mwrite(_)).Times(AtLeast(0)).WillRepeatedly(
            WithArg<0>(Invoke(print_packet)));
        gc_hub0.register_port(m);
        printer_.reset(m);
    }

    /** Injects a packet to the interface. This acts as if a different node on
        the CANbus had sent that packet.

        Example:
        send_packet(":X195B4001N05010101FFFF0000;");

        @param gc_packet the packet in GridConnect format, including the leading
        : and trailing ;
    */
    void send_packet(const string &gc_packet)
    {
        Buffer<HubData> *packet;
        mainBufferPool->alloc(&packet);
        packet->data()->assign(gc_packet);
        packet->data()->skipMember_ = &canBus_;
        gc_hub0.send(packet);
    }

/** Injects an incoming packet to the interface and expects that the node
    will send out a response packet for it.

    As a side effect, clears all pending expectations on the CANbus.

    Example:
    send_packet_and_expect_response(":X198F4001N05010101FFFF0000;",
                                    ":X194C412DN05010101FFFF0000;");

    @param pkt is the packet to inject, in GridConnect format.
    @param resp is the response to expect, also in GridConnect format.
*/
#define send_packet_and_expect_response(pkt, resp)                             \
    do                                                                         \
    {                                                                          \
        expect_packet(resp);                                                   \
        send_packet_and_flush_expect(pkt);                                     \
    } while (0)

    void send_packet_and_flush_expect(const string &pkt)
    {
        send_packet(pkt);
        wait();
        Mock::VerifyAndClear(&canBus_);
    }

    /// Helper object for setting expectations on the packets sent on the bus.
    NiceMock<MockSend> canBus_;
    /// Object for debug-printing every packet (if requested).
    std::unique_ptr<HubPort> printer_;
};

namespace nmranet
{

/*
const char *Node::MANUFACTURER = "Stuart W. Baker";
const char *Node::HARDWARE_REV = "N/A";
const char *Node::SOFTWARE_REV = "0.1";

const size_t Datagram::POOL_SIZE = 10;
const size_t Datagram::THREAD_STACK_SIZE = 512;
const size_t Stream::CHANNELS_PER_NODE = 10;
const uint16_t Stream::MAX_BUFFER_SIZE = 512;*/

static const NodeID TEST_NODE_ID = 0x02010d000003ULL;

/** Test fixture base class with helper methods for exercising the asynchronous
 * interface code.
 *
 * Usage:
 *
 * Inherit your test fixture class from AsyncIfTest.
 */
class AsyncIfTest : public AsyncCanTest
{
protected:
    AsyncIfTest()
        : pendingAliasAllocation_(false)
    {
        ifCan_.reset(new IfCan(&g_executor, &can_hub0, 10, 10, 5));
        ifCan_->local_aliases()->add(TEST_NODE_ID, 0x22A);
    }

    ~AsyncIfTest()
    {
        wait();
        if (pendingAliasAllocation_)
        {
            ifCan_->alias_allocator()->TEST_finish_pending_allocation();
            wait();
        }
    }

    friend class ::TrainTestHelper;

    /** Creates an alias allocator flow, and injects an already allocated
     *  alias. */
    void create_allocated_alias()
    {
        ifCan_->set_alias_allocator(
            new AliasAllocator(TEST_NODE_ID, ifCan_.get()));
        Buffer<AliasInfo> *a;
        mainBufferPool->alloc(&a);
        a->data()->alias = 0x33A;
        a->data()->state = AliasInfo::STATE_RESERVED;
        ifCan_->local_aliases()->add(AliasCache::RESERVED_ALIAS_NODE_ID,
                                     a->data()->alias);
        ifCan_->alias_allocator()->reserved_aliases()->insert(a);
        aliasSeed_ = 0x44C;
        pendingAliasAllocation_ = false;
    }

    void expect_next_alias_allocation(NodeAlias a = 0)
    {
        pendingAliasAllocation_ = true;
        if (!a)
        {
            ifCan_->alias_allocator()->seed_ = aliasSeed_;
            a = aliasSeed_;
            aliasSeed_++;
        }
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X17020%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X1610D%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X15000%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X14003%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();

        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X10700%03XN;", a)))
            .Times(AtMost(1))
            .RetiresOnSaturation();
    }

    BarrierNotifiable *get_notifiable()
    {
        bn_.reset(&n_);
        return &bn_;
    }

    void wait_for_notification()
    {
        n_.wait_for_notification();
    }

    SyncNotifiable n_;
    BarrierNotifiable bn_;

    /// The interface under test.
    std::unique_ptr<IfCan> ifCan_;
    /** Temporary object used to send aliases around in the alias allocator
     *  flow. */
    AliasInfo testAlias_;
    /// The next alias we will make the allocator create.
    NodeAlias aliasSeed_;
    /// true if we have a pending async alias allocation task.
    bool pendingAliasAllocation_;
};

class AsyncNodeTest : public AsyncIfTest
{
protected:
    AsyncNodeTest()
        : eventService_(ifCan_.get())
    {
        EXPECT_CALL(canBus_, mwrite(":X1910022AN02010D000003;")).Times(1);
        ownedNode_.reset(new DefaultNode(ifCan_.get(), TEST_NODE_ID));
        node_ = ownedNode_.get();
        ifCan_->add_addressed_message_support();
        wait();
        // AddEventHandlerToIf(ifCan_.get());
    }

    ~AsyncNodeTest()
    {
        wait_for_event_thread();
    }

    void wait_for_event_thread()
    {
        while (EventService::instance->event_processing_pending())
        {
            usleep(100);
        }
        AsyncIfTest::wait();
    }

    EventService eventService_;
    std::unique_ptr<DefaultNode> ownedNode_;
    Node *node_;
};

class MockMessageHandler : public MessageHandler
{
public:
    MOCK_METHOD2(handle_message,
                 void(NMRAnetMessage *message, unsigned priority));
    virtual void send(Buffer<NMRAnetMessage> *message, unsigned priority)
    {
        handle_message(message->data(), priority);
        message->unref();
    }
};

MATCHER_P(IsBufferValue, id, "")
{
    uint64_t value = htobe64(id);
    if (arg.size() != 8)
        return false;
    if (memcmp(&value, arg.data(), 8))
        return false;
    return true;
}

MATCHER_P(IsBufferValueString, expected, "")
{
    string s(expected);
    return arg == s;
}

MATCHER_P(IsBufferNodeValue, id, "")
{
    uint64_t value = htobe64(id);
    if (arg->used() != 6)
        return false;
    uint8_t *expected = reinterpret_cast<uint8_t *>(&value) + 2;
    uint8_t *actual = static_cast<uint8_t *>(arg->start());
    if (memcmp(expected, actual, 6))
    {
        for (int i = 0; i < 6; ++i)
        {
            if (expected[i] != actual[i])
            {
                LOG(INFO, "mismatch at position %d, expected %02x actual %02x",
                    i, expected[i], actual[i]);
            }
        }
        return false;
    }
    return true;
}

MATCHER_P(IsBufferNodeValueString, id, "")
{
    uint64_t value = htobe64(id);
    if (arg.size() != 6)
        return false;
    uint8_t *expected = reinterpret_cast<uint8_t *>(&value) + 2;
    uint8_t *actual = static_cast<uint8_t *>(arg->start());
    if (memcmp(expected, actual, 6))
    {
        for (int i = 0; i < 6; ++i)
        {
            if (expected[i] != actual[i])
            {
                LOG(INFO, "mismatch at position %d, expected %02x actual %02x",
                    i, expected[i], actual[i]);
            }
        }
        return false;
    }
    return true;
}

} // namespace nmranet

#endif // _UTILS_ASYNC_IF_TEST_HELPER_HXX_
<commit_msg>Clears the mock after the initialization sequence is complete.<commit_after>// Helper classes for writing unittests testing the entire asynchronous
// stack. Allows to send incoming messages (in gridconnect format) and set
// expectations on messages produced.
//
// Only include this file in unittests.

#ifndef _UTILS_ASYNC_IF_TEST_HELPER_HXX_
#define _UTILS_ASYNC_IF_TEST_HELPER_HXX_

#include "nmranet/AliasAllocator.hxx"
#include "nmranet/IfCan.hxx"
#include "nmranet/EventService.hxx"
#include "nmranet/DefaultNode.hxx"
#include "nmranet_config.h"
#include "utils/GridConnectHub.hxx"
#include "utils/test_main.hxx"

using ::testing::AtLeast;
using ::testing::AtMost;
using ::testing::Eq;
using ::testing::Field;
using ::testing::Invoke;
using ::testing::IsNull;
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::StrCaseEq;
using ::testing::StrictMock;
using ::testing::WithArg;
using ::testing::_;

class TrainTestHelper;

///@todo(balazs.racz) remove
// void (*g_invoke)(Notifiable *) = &InvokeNotification;

HubFlow gc_hub0(&g_service);
CanHubFlow can_hub0(&g_service);
GCAdapterBase *g_gc_adapter = nullptr;

HubFlow gc_hub1(&g_service);
CanHubFlow can_hub1(&g_service);
GCAdapterBase *g_gc_adapter1 = nullptr;

/** Helper class for setting expectation on the CANbus traffic in unit
 * tests. */
class MockSend : public HubPort
{
public:
    MockSend()
        : HubPort(&g_service)
    {
    }

    MOCK_METHOD1(mwrite, void(const string &s));

    virtual Action entry()
    {
        string s(message()->data()->data(), message()->data()->size());
        mwrite(s);
        return release_and_exit();
    }
};

void InvokeNotification(Notifiable *done)
{
    done->notify();
}

static void print_packet(const string &pkt)
{
    fprintf(stderr, "%s\n", pkt.c_str());
}

class AsyncCanTest : public testing::Test
{
public:
    static void SetUpTestCase()
    {
        g_gc_adapter =
            GCAdapterBase::CreateGridConnectAdapter(&gc_hub0, &can_hub0, false);
    }

    static void TearDownTestCase()
    {
        delete g_gc_adapter;
    }

protected:
    AsyncCanTest()
    {
        gc_hub0.register_port(&canBus_);
    }

    ~AsyncCanTest()
    {
        gc_hub0.unregister_port(&canBus_);
        if (printer_.get())
        {
            gc_hub0.unregister_port(printer_.get());
        }
    }

    /** Delays the current thread until we are certain that all asynchrnous
        processing has completed. */
    void wait()
    {
        wait_for_main_executor();
    }

/** Adds an expectation that the code will send a packet to the CANbus.

    Example:
    expect_packet(":X1954412DN05010101FFFF0000;");

    @param gc_packet the packet in GridConnect format, including the leading
    : and trailing ;
*/
#define expect_packet(gc_packet)                                               \
    EXPECT_CALL(canBus_, mwrite(StrCaseEq(gc_packet)))

    /** Ignores all produced packets.
     *
     *  Tihs can be used in tests where the expectations are tested in a higher
     *  level than monitoring the CANbus traffic.
    */
    void expect_any_packet()
    {
        EXPECT_CALL(canBus_, mwrite(_)).Times(AtLeast(0)).WillRepeatedly(
            WithArg<0>(Invoke(print_packet)));
    }

    /** Prints all packets sent to the canbus until the end of the current test
     * function.
    */
    void print_all_packets()
    {
        NiceMock<MockSend> *m = new NiceMock<MockSend>();
        EXPECT_CALL(*m, mwrite(_)).Times(AtLeast(0)).WillRepeatedly(
            WithArg<0>(Invoke(print_packet)));
        gc_hub0.register_port(m);
        printer_.reset(m);
    }

    /** Injects a packet to the interface. This acts as if a different node on
        the CANbus had sent that packet.

        Example:
        send_packet(":X195B4001N05010101FFFF0000;");

        @param gc_packet the packet in GridConnect format, including the leading
        : and trailing ;
    */
    void send_packet(const string &gc_packet)
    {
        Buffer<HubData> *packet;
        mainBufferPool->alloc(&packet);
        packet->data()->assign(gc_packet);
        packet->data()->skipMember_ = &canBus_;
        gc_hub0.send(packet);
    }

/** Injects an incoming packet to the interface and expects that the node
    will send out a response packet for it.

    As a side effect, clears all pending expectations on the CANbus.

    Example:
    send_packet_and_expect_response(":X198F4001N05010101FFFF0000;",
                                    ":X194C412DN05010101FFFF0000;");

    @param pkt is the packet to inject, in GridConnect format.
    @param resp is the response to expect, also in GridConnect format.
*/
#define send_packet_and_expect_response(pkt, resp)                             \
    do                                                                         \
    {                                                                          \
        expect_packet(resp);                                                   \
        send_packet_and_flush_expect(pkt);                                     \
    } while (0)

    void send_packet_and_flush_expect(const string &pkt)
    {
        send_packet(pkt);
        wait();
        Mock::VerifyAndClear(&canBus_);
    }

    /// Helper object for setting expectations on the packets sent on the bus.
    NiceMock<MockSend> canBus_;
    /// Object for debug-printing every packet (if requested).
    std::unique_ptr<HubPort> printer_;
};

namespace nmranet
{

/*
const char *Node::MANUFACTURER = "Stuart W. Baker";
const char *Node::HARDWARE_REV = "N/A";
const char *Node::SOFTWARE_REV = "0.1";

const size_t Datagram::POOL_SIZE = 10;
const size_t Datagram::THREAD_STACK_SIZE = 512;
const size_t Stream::CHANNELS_PER_NODE = 10;
const uint16_t Stream::MAX_BUFFER_SIZE = 512;*/

static const NodeID TEST_NODE_ID = 0x02010d000003ULL;

/** Test fixture base class with helper methods for exercising the asynchronous
 * interface code.
 *
 * Usage:
 *
 * Inherit your test fixture class from AsyncIfTest.
 */
class AsyncIfTest : public AsyncCanTest
{
protected:
    AsyncIfTest()
        : pendingAliasAllocation_(false)
    {
        ifCan_.reset(new IfCan(&g_executor, &can_hub0, 10, 10, 5));
        ifCan_->local_aliases()->add(TEST_NODE_ID, 0x22A);
    }

    ~AsyncIfTest()
    {
        wait();
        if (pendingAliasAllocation_)
        {
            ifCan_->alias_allocator()->TEST_finish_pending_allocation();
            wait();
        }
    }

    friend class ::TrainTestHelper;

    /** Creates an alias allocator flow, and injects an already allocated
     *  alias. */
    void create_allocated_alias()
    {
        ifCan_->set_alias_allocator(
            new AliasAllocator(TEST_NODE_ID, ifCan_.get()));
        Buffer<AliasInfo> *a;
        mainBufferPool->alloc(&a);
        a->data()->alias = 0x33A;
        a->data()->state = AliasInfo::STATE_RESERVED;
        ifCan_->local_aliases()->add(AliasCache::RESERVED_ALIAS_NODE_ID,
                                     a->data()->alias);
        ifCan_->alias_allocator()->reserved_aliases()->insert(a);
        aliasSeed_ = 0x44C;
        pendingAliasAllocation_ = false;
    }

    void expect_next_alias_allocation(NodeAlias a = 0)
    {
        pendingAliasAllocation_ = true;
        if (!a)
        {
            ifCan_->alias_allocator()->seed_ = aliasSeed_;
            a = aliasSeed_;
            aliasSeed_++;
        }
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X17020%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X1610D%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X15000%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();
        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X14003%03XN;", a)))
            .Times(1)
            .RetiresOnSaturation();

        EXPECT_CALL(canBus_, mwrite(StringPrintf(":X10700%03XN;", a)))
            .Times(AtMost(1))
            .RetiresOnSaturation();
    }

    BarrierNotifiable *get_notifiable()
    {
        bn_.reset(&n_);
        return &bn_;
    }

    void wait_for_notification()
    {
        n_.wait_for_notification();
    }

    SyncNotifiable n_;
    BarrierNotifiable bn_;

    /// The interface under test.
    std::unique_ptr<IfCan> ifCan_;
    /** Temporary object used to send aliases around in the alias allocator
     *  flow. */
    AliasInfo testAlias_;
    /// The next alias we will make the allocator create.
    NodeAlias aliasSeed_;
    /// true if we have a pending async alias allocation task.
    bool pendingAliasAllocation_;
};

class AsyncNodeTest : public AsyncIfTest
{
protected:
    AsyncNodeTest()
        : eventService_(ifCan_.get())
    {
        EXPECT_CALL(canBus_, mwrite(":X1910022AN02010D000003;")).Times(1);
        ownedNode_.reset(new DefaultNode(ifCan_.get(), TEST_NODE_ID));
        node_ = ownedNode_.get();
        ifCan_->add_addressed_message_support();
        wait();
        Mock::VerifyAndClear(&canBus_);
        // AddEventHandlerToIf(ifCan_.get());
    }

    ~AsyncNodeTest()
    {
        wait_for_event_thread();
    }

    void wait_for_event_thread()
    {
        while (EventService::instance->event_processing_pending())
        {
            usleep(100);
        }
        AsyncIfTest::wait();
    }

    EventService eventService_;
    std::unique_ptr<DefaultNode> ownedNode_;
    Node *node_;
};

class MockMessageHandler : public MessageHandler
{
public:
    MOCK_METHOD2(handle_message,
                 void(NMRAnetMessage *message, unsigned priority));
    virtual void send(Buffer<NMRAnetMessage> *message, unsigned priority)
    {
        handle_message(message->data(), priority);
        message->unref();
    }
};

MATCHER_P(IsBufferValue, id, "")
{
    uint64_t value = htobe64(id);
    if (arg.size() != 8)
        return false;
    if (memcmp(&value, arg.data(), 8))
        return false;
    return true;
}

MATCHER_P(IsBufferValueString, expected, "")
{
    string s(expected);
    return arg == s;
}

MATCHER_P(IsBufferNodeValue, id, "")
{
    uint64_t value = htobe64(id);
    if (arg->used() != 6)
        return false;
    uint8_t *expected = reinterpret_cast<uint8_t *>(&value) + 2;
    uint8_t *actual = static_cast<uint8_t *>(arg->start());
    if (memcmp(expected, actual, 6))
    {
        for (int i = 0; i < 6; ++i)
        {
            if (expected[i] != actual[i])
            {
                LOG(INFO, "mismatch at position %d, expected %02x actual %02x",
                    i, expected[i], actual[i]);
            }
        }
        return false;
    }
    return true;
}

MATCHER_P(IsBufferNodeValueString, id, "")
{
    uint64_t value = htobe64(id);
    if (arg.size() != 6)
        return false;
    uint8_t *expected = reinterpret_cast<uint8_t *>(&value) + 2;
    uint8_t *actual = static_cast<uint8_t *>(arg->start());
    if (memcmp(expected, actual, 6))
    {
        for (int i = 0; i < 6; ++i)
        {
            if (expected[i] != actual[i])
            {
                LOG(INFO, "mismatch at position %d, expected %02x actual %02x",
                    i, expected[i], actual[i]);
            }
        }
        return false;
    }
    return true;
}

} // namespace nmranet

#endif // _UTILS_ASYNC_IF_TEST_HELPER_HXX_
<|endoftext|>


<commit_before>// 	$Id$
// test for correctness of gradients on a given cell

// deal_II_libraries.g=-ldeal_II_2d.g
// deal_II_libraries=-ldeal_II_2d

#include <grid/tria.h>
#include <grid/tria_boundary.h>
#include <grid/dof.h>
#include <grid/grid_generator.h>
#include <fe/fe_values.h>
#include <fe/fe_lib.lagrange.h>
#include <base/quadrature_lib.h>
#include <grid/tria_iterator.h>
#include <grid/dof_accessor.h>
#include <lac/vector.h>

int main () {
  Triangulation<2> tria;
  GridGenerator::hyper_cube (tria,0,1);

  FEQ1<2> fe;
  DoFHandler<2> dof(&tria);
  dof.distribute_dofs(fe);

  StraightBoundary<2> b;
  QTrapez<2> q;
  FEValues<2> fevalues(fe,q,update_second_derivatives);

  Vector<double> val(4);

  cout << "------------------------------------------------------------" << endl
       << "Testing transformation of 2nd derivatives of shape function:" << endl;

				   // test for each of the four
				   // shape functions. first loop:
				   // unit cell, second loop:
				   // one vertex moved
  bool testcase_succeeded = true;
  for (unsigned int loop=0; loop<2; ++loop)
    {
      cout << "Test loop: " << loop << endl
	   << "-----------" << endl;

      				   // move one vertex of the only cell
      if (loop==1)
	tria.begin_active()->vertex(2)(0) = 2;
      fevalues.reinit (dof.begin_active());

      for (unsigned int vertex=0; vertex<4; ++vertex)
	{
	  val.clear ();
	  val(vertex) = 1;

	  vector<Tensor<2,2> > derivs(4);
	  fevalues.get_function_2nd_derivatives (val, derivs);

	  cout << "  Vertex " << vertex << ": ";
	  switch (loop)
	    {
	      case 0:
		    for (unsigned int point=0; point<4; ++point)
		      {
							 // on the unit cell,
			bool ok=true;

			if ((derivs[point][0][0] != 0) ||
			    (derivs[point][1][1] != 0))
			  ok = false;

			switch (vertex)
			  {
			    case 0:
			    case 2:
				  if ((derivs[point][0][1] != 1) ||
				      (derivs[point][1][0] != 1))
				    ok = false;
				  break;
			    case 1:
			    case 3:
				  if ((derivs[point][0][1] != -1) ||
				      (derivs[point][1][0] != -1))
				    ok = false;
				  break;
			  };

			if (!ok)
			  {
			    testcase_succeeded = false;
			    cout << "WRONG! ";
			  }
			else
			  cout << "OK ";
		      };
		    break;

	      case 1:
						     // are these numbers ok?
						     // I have never checked
						     // them, exept for the
						     // symmetry of the tensors
						     // and some of the signs of
						     // the entries! Someone
						     // should really try to
						     // verify at least
						     // some of the numbers
		    static double _true_value[4][4][2][2]
		      = { { {{0,1},
			     {1,0}},
			    {{0,0},
			     {0,0}},
			    {{0,1},
			     {1,-2}},
			    {{0,0},
			     {0,0}}  },
			  { {{0,-1},
			     {-1,0}},
			    {{0,0},
			     {0,0}},
			    {{0,-1},
			     {-1,2}},
			    {{0,0},
			     {0,0}}  },
			  { {{0,0},
			     {0,0}},
			    {{0,-.25},
			     {-.25,0}},
			    {{0,0},
			     {0,0}},
			    {{0,-.25},
			     {-.25,0.5}}  },
			  { {{0,0},
			     {0,0}},
			    {{0,.25},
			     {.25,0}},
			    {{0,0},
			     {0,0}},
			    {{0,.25},
			     {.25,-.5}}  }  };
		    static Tensor<2,2> true_value[4][4]
		      = {{ Tensor<2,2>(_true_value[0][0]),
			   Tensor<2,2>(_true_value[0][1]),
			   Tensor<2,2>(_true_value[0][2]),
			   Tensor<2,2>(_true_value[0][3])  },
			 { Tensor<2,2>(_true_value[1][0]),
			   Tensor<2,2>(_true_value[1][1]),
			   Tensor<2,2>(_true_value[1][2]),
			   Tensor<2,2>(_true_value[1][3])  },
			 { Tensor<2,2>(_true_value[2][0]),
			   Tensor<2,2>(_true_value[2][1]),
			   Tensor<2,2>(_true_value[2][2]),
			   Tensor<2,2>(_true_value[2][3])  },
			 { Tensor<2,2>(_true_value[3][0]),
			   Tensor<2,2>(_true_value[3][1]),
			   Tensor<2,2>(_true_value[3][2]),
			   Tensor<2,2>(_true_value[3][3])  }};

		    for (unsigned int point=0; point<4; ++point)
		      {
			if (derivs[point] != true_value[vertex][point])
			  {
			    testcase_succeeded = false;
			    cout << "WRONG! ";
			  }
			else
			  cout << "OK ";
		      };
		    break;
	    };

	  cout << endl;
	};
    };

  cout << "------------------------------------------------------" << endl;

  if (testcase_succeeded)
    return 0;
  else
    return 1;
};
<commit_msg>Finally produce something reasonable.<commit_after>// 	$Id$
// test for correctness of gradients on a given cell

// deal_II_libraries.g=-ldeal_II_2d.g
// deal_II_libraries=-ldeal_II_2d

#include <grid/tria.h>
#include <grid/tria_boundary.h>
#include <grid/dof.h>
#include <grid/grid_generator.h>
#include <fe/fe_values.h>
#include <fe/fe_lib.lagrange.h>
#include <base/quadrature_lib.h>
#include <grid/tria_iterator.h>
#include <grid/dof_accessor.h>
#include <lac/vector.h>

int main () {
  Triangulation<2> tria;
  GridGenerator::hyper_cube (tria,0,1);

  FEQ1<2> fe;
  DoFHandler<2> dof(&tria);
  dof.distribute_dofs(fe);

  StraightBoundary<2> b;
  QTrapez<2> q;
  FEValues<2> fevalues(fe,q,update_second_derivatives);

  Vector<double> val(4);

  cout << "------------------------------------------------------------" << endl
       << "Testing transformation of 2nd derivatives of shape function:" << endl;

				   // test for each of the four
				   // shape functions. first loop:
				   // unit cell, second loop:
				   // one vertex moved
  for (unsigned int loop=0; loop<2; ++loop)
    {
      cout << "Test loop: " << loop << endl
	   << "-----------" << endl;

      				   // move one vertex of the only cell
      if (loop==1)
	tria.begin_active()->vertex(2)(0) = 2;
      fevalues.reinit (dof.begin_active());

      for (unsigned int vertex=0; vertex<4; ++vertex)
	{
	  val.clear ();
	  val(vertex) = 1;

	  vector<Tensor<2,2> > derivs(4);
	  fevalues.get_function_2nd_derivatives (val, derivs);

	  cout << "Vertex " << vertex << ": " << endl;
	  for (unsigned int point=0; point<4; ++point)
	    for (unsigned int component=0; component<2; ++component)
	      cout << derivs[point][component] << endl;

	  cout << endl;
	};
    };
};
<|endoftext|>