<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1)
		thread1_id = p_uthread_current_id ();
	else
		thread2_id = p_uthread_current_id ();

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	if (self_thread_free) {
		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		p_free (last_tls);

		p_uthread_replace_local (tls_key, (ppointer) NULL);
	}

	p_uthread_exit (counter);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL) == NULL);

	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);
	p_uthread_replace_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL));
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_free (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == 0);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_uthread_free (thr1);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Fix thread priority checks<commit_after>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1)
		thread1_id = p_uthread_current_id ();
	else
		thread2_id = p_uthread_current_id ();

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	if (self_thread_free) {
		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		p_free (last_tls);

		p_uthread_replace_local (tls_key, (ppointer) NULL);
	}

	p_uthread_exit (counter);
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL) == NULL);

	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);
	p_uthread_replace_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	vtable.malloc	= (ppointer (*)(psize)) malloc;
	vtable.realloc	= (ppointer (*)(ppointer, psize)) realloc;
	vtable.free	= (void (*)(ppointer)) free;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL) == FALSE);
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_free (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_uthread_free (thr1);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);
	p_uthread_free (thr1);
	p_uthread_free (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before><commit_msg>removed tests for the server queue.  this is just an interface so no tests needed.<commit_after><|endoftext|>


<commit_before><commit_msg>Adding VarLenPoolBasicTest<commit_after><|endoftext|>


<commit_before>#include "test_comm.h"

#include <libmesh/dof_map.h>
#include <libmesh/elem.h>
#include <libmesh/equation_systems.h>
#include <libmesh/fe_base.h>
#include <libmesh/fe_interface.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/numeric_vector.h>
#include <libmesh/system.h>

#include <vector>

#include "libmesh_cppunit.h"

using namespace libMesh;

template <ElemType elem_type>
class RationalMapTest : public CppUnit::TestCase {

private:
  unsigned int _dim, _nx, _ny, _nz;
  Elem *_elem;
  std::vector<dof_id_type> _dof_indices;
  FEBase * _fe;
  Mesh * _mesh;
  System * _sys;
  EquationSystems * _es;

public:
  void setUp()
  {
    _mesh = new Mesh(*TestCommWorld);
    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    _dim = test_elem->dim();
    const unsigned int ny = _dim > 1;
    const unsigned int nz = _dim > 2;

    // Make sure we can handle non-zero weight indices
    _mesh->add_node_integer("buffer integer1");
    _mesh->add_node_integer("buffer integer2");
    unsigned char weight_index = cast_int<unsigned char>
      (_mesh->add_node_datum<Real>("rational_weight"));
    libmesh_assert_not_equal_to(weight_index, 0);

    _mesh->set_default_mapping_type(RATIONAL_BERNSTEIN_MAP);
    _mesh->set_default_mapping_data(weight_index);

    MeshTools::Generation::build_cube (*_mesh,
                                       1, ny, nz,
                                       0., 1., 0., ny, 0., nz,
                                       elem_type);

    for (auto elem : _mesh->element_ptr_range())
      {
        CPPUNIT_ASSERT_EQUAL(elem->mapping_type(), RATIONAL_BERNSTEIN_MAP);
        CPPUNIT_ASSERT_EQUAL(elem->mapping_data(), weight_index);
      }

    // Transform the cube / square into a rotated quarter-annulus,
    // with central axis at (-.5, 0) and radii ranging from .5 to 1.5

    for (auto node : _mesh->node_ptr_range())
      {
        Real & x = (*node)(0);
        Real & y = (*node)(1);
        node->set_extra_datum<Real>(weight_index, 1);
        if (y > .6)
          {
            y = .5 + x;
            x = -.5;
          }
        else if (y > .4)
          {
            y = .5 + x;
            x = y - .5;
            node->set_extra_datum<Real>(weight_index, sqrt(Real(2))/2);
          }
      }

    _es = new EquationSystems(*_mesh);
    _sys = &(_es->add_system<System> ("SimpleSystem"));
    _sys->add_variable("u", FIRST);
    _es->init();

    _fe = FEBase::build(_dim, _sys->variable_type("u")).release();
    _fe->get_xyz();
    _fe->get_phi();
    _fe->get_dphi();
    _fe->get_dphidx();
#if LIBMESH_DIM > 1
    _fe->get_dphidy();
#endif
#if LIBMESH_DIM > 2
    _fe->get_dphidz();
#endif

    auto rng = _mesh->active_local_element_ptr_range();
    _elem = rng.begin() == rng.end() ? nullptr : *(rng.begin());

    _nx = 10;
    _ny = (_dim > 1) ? _nx : 0;
    _nz = (_dim > 2) ? _nx : 0;
  }

  void tearDown()
  {
    delete _fe;
    delete _es;
    delete _mesh;
  }

  void testMap()
  {
    // Handle the "more processors than elements" case
    if (!_elem)
      return;

    // These tests require exceptions to be enabled because a
    // TypeTensor::solve() call down in Elem::contains_point()
    // actually throws a non-fatal exception for a certain Point which
    // is not in the Elem. When exceptions are not enabled, this test
    // simply aborts.
#ifdef LIBMESH_ENABLE_EXCEPTIONS
    for (unsigned int j=0; j != _ny+1; ++j)
      for (unsigned int k=0; k != _nz+1; ++k)
        {
          for (int i=-1; i != int(_nx+2); ++i)
            {
              Real r = (Real(i)/_nx) + 0.5,
                   theta = (Real(j)/_nx)*pi/2,
                   z = (Real(k)/_nx);
              Real x = -.5 + r * std::cos(theta),
                   y = r * std::sin(theta);
              Point p(x,y,z);
              // Test for false negatives
              if (i >= 0 && i <= int(_nx))
                CPPUNIT_ASSERT(_elem->contains_point(p));
              // Also test for false positives
              else
                CPPUNIT_ASSERT(!_elem->contains_point(p));
            }
        }
#endif
  }
};

#define INSTANTIATE_RATIONALMAP_TEST(elemtype)                          \
  class RationalMapTest_##elemtype : public RationalMapTest<elemtype> { \
  public:                                                               \
  CPPUNIT_TEST_SUITE( RationalMapTest_##elemtype );                     \
  CPPUNIT_TEST( testMap );                                              \
  CPPUNIT_TEST_SUITE_END();                                             \
  };                                                                    \
                                                                        \
  CPPUNIT_TEST_SUITE_REGISTRATION( RationalMapTest_##elemtype );

INSTANTIATE_RATIONALMAP_TEST(EDGE3);
INSTANTIATE_RATIONALMAP_TEST(QUAD8);
INSTANTIATE_RATIONALMAP_TEST(QUAD9);
INSTANTIATE_RATIONALMAP_TEST(HEX20);
INSTANTIATE_RATIONALMAP_TEST(HEX27);
<commit_msg>More accurate unit test name<commit_after>#include "test_comm.h"

#include <libmesh/dof_map.h>
#include <libmesh/elem.h>
#include <libmesh/equation_systems.h>
#include <libmesh/fe_base.h>
#include <libmesh/fe_interface.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/numeric_vector.h>
#include <libmesh/system.h>

#include <vector>

#include "libmesh_cppunit.h"

using namespace libMesh;

template <ElemType elem_type>
class RationalMapTest : public CppUnit::TestCase {

private:
  unsigned int _dim, _nx, _ny, _nz;
  Elem *_elem;
  std::vector<dof_id_type> _dof_indices;
  FEBase * _fe;
  Mesh * _mesh;
  System * _sys;
  EquationSystems * _es;

public:
  void setUp()
  {
    _mesh = new Mesh(*TestCommWorld);
    const std::unique_ptr<Elem> test_elem = Elem::build(elem_type);
    _dim = test_elem->dim();
    const unsigned int ny = _dim > 1;
    const unsigned int nz = _dim > 2;

    // Make sure we can handle non-zero weight indices
    _mesh->add_node_integer("buffer integer1");
    _mesh->add_node_integer("buffer integer2");
    unsigned char weight_index = cast_int<unsigned char>
      (_mesh->add_node_datum<Real>("rational_weight"));
    libmesh_assert_not_equal_to(weight_index, 0);

    _mesh->set_default_mapping_type(RATIONAL_BERNSTEIN_MAP);
    _mesh->set_default_mapping_data(weight_index);

    MeshTools::Generation::build_cube (*_mesh,
                                       1, ny, nz,
                                       0., 1., 0., ny, 0., nz,
                                       elem_type);

    for (auto elem : _mesh->element_ptr_range())
      {
        CPPUNIT_ASSERT_EQUAL(elem->mapping_type(), RATIONAL_BERNSTEIN_MAP);
        CPPUNIT_ASSERT_EQUAL(elem->mapping_data(), weight_index);
      }

    // Transform the cube / square into a rotated quarter-annulus,
    // with central axis at (-.5, 0) and radii ranging from .5 to 1.5

    for (auto node : _mesh->node_ptr_range())
      {
        Real & x = (*node)(0);
        Real & y = (*node)(1);
        node->set_extra_datum<Real>(weight_index, 1);
        if (y > .6)
          {
            y = .5 + x;
            x = -.5;
          }
        else if (y > .4)
          {
            y = .5 + x;
            x = y - .5;
            node->set_extra_datum<Real>(weight_index, sqrt(Real(2))/2);
          }
      }

    _es = new EquationSystems(*_mesh);
    _sys = &(_es->add_system<System> ("SimpleSystem"));
    _sys->add_variable("u", FIRST);
    _es->init();

    _fe = FEBase::build(_dim, _sys->variable_type("u")).release();
    _fe->get_xyz();
    _fe->get_phi();
    _fe->get_dphi();
    _fe->get_dphidx();
#if LIBMESH_DIM > 1
    _fe->get_dphidy();
#endif
#if LIBMESH_DIM > 2
    _fe->get_dphidz();
#endif

    auto rng = _mesh->active_local_element_ptr_range();
    _elem = rng.begin() == rng.end() ? nullptr : *(rng.begin());

    _nx = 10;
    _ny = (_dim > 1) ? _nx : 0;
    _nz = (_dim > 2) ? _nx : 0;
  }

  void tearDown()
  {
    delete _fe;
    delete _es;
    delete _mesh;
  }

  void testContainsPoint()
  {
    // Handle the "more processors than elements" case
    if (!_elem)
      return;

    // These tests require exceptions to be enabled because a
    // TypeTensor::solve() call down in Elem::contains_point()
    // actually throws a non-fatal exception for a certain Point which
    // is not in the Elem. When exceptions are not enabled, this test
    // simply aborts.
#ifdef LIBMESH_ENABLE_EXCEPTIONS
    for (unsigned int j=0; j != _ny+1; ++j)
      for (unsigned int k=0; k != _nz+1; ++k)
        {
          for (int i=-1; i != int(_nx+2); ++i)
            {
              Real r = (Real(i)/_nx) + 0.5,
                   theta = (Real(j)/_nx)*pi/2,
                   z = (Real(k)/_nx);
              Real x = -.5 + r * std::cos(theta),
                   y = r * std::sin(theta);
              Point p(x,y,z);
              // Test for false negatives
              if (i >= 0 && i <= int(_nx))
                CPPUNIT_ASSERT(_elem->contains_point(p));
              // Also test for false positives
              else
                CPPUNIT_ASSERT(!_elem->contains_point(p));
            }
        }
#endif
  }
};

#define INSTANTIATE_RATIONALMAP_TEST(elemtype)                          \
  class RationalMapTest_##elemtype : public RationalMapTest<elemtype> { \
  public:                                                               \
  CPPUNIT_TEST_SUITE( RationalMapTest_##elemtype );                     \
  CPPUNIT_TEST( testContainsPoint );                                    \
  CPPUNIT_TEST_SUITE_END();                                             \
  };                                                                    \
                                                                        \
  CPPUNIT_TEST_SUITE_REGISTRATION( RationalMapTest_##elemtype );

INSTANTIATE_RATIONALMAP_TEST(EDGE3);
INSTANTIATE_RATIONALMAP_TEST(QUAD8);
INSTANTIATE_RATIONALMAP_TEST(QUAD9);
INSTANTIATE_RATIONALMAP_TEST(HEX20);
INSTANTIATE_RATIONALMAP_TEST(HEX27);
<|endoftext|>


<commit_before>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/dof_map.h>
#include <libmesh/system.h>
#include <libmesh/mesh_function.h>
#include <libmesh/numeric_vector.h>
#include <libmesh/elem.h>

#include "test_comm.h"

// THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
// std::auto_ptr, which in turn produces -Wdeprecated-declarations
// warnings.  These can be ignored in GCC as long as we wrap the
// offending code in appropriate pragmas.  We can't get away with a
// single ignore_warnings.h inclusion at the beginning of this file,
// since the libmesh headers pull in a restore_warnings.h at some
// point.  We also don't bother restoring warnings at the end of this
// file since it's not a header.
#include <libmesh/ignore_warnings.h>

using namespace libMesh;

Number projection_function (const Point & p,
                            const Parameters &,
                            const std::string &,
                            const std::string &)
{
  return
    cos(.5*libMesh::pi*p(0)) *
    sin(.5*libMesh::pi*p(1)) *
    cos(.5*libMesh::pi*p(2));
}

class MeshFunctionTest : public CppUnit::TestCase
{
  /**
   * Tests for general MeshFunction capability.
   */
public:
  CPPUNIT_TEST_SUITE( MeshFunctionTest );

#if LIBMESH_DIM > 1
  CPPUNIT_TEST( test_p_level );
#endif

  CPPUNIT_TEST_SUITE_END();

protected:

public:
  void setUp() {}

  void tearDown() {}

  // test that mesh function works correctly with non-zero
  // Elem::p_level() values.
  void test_p_level()
  {
    ReplicatedMesh mesh(*TestCommWorld);

    MeshTools::Generation::build_cube (mesh,
                                       5, 5, 5,
                                       0., 1.,
                                       0., 1.,
                                       0., 1.,
                                       HEX20);

    // Bump the p-level for all elements. We will create a system with
    // a FIRST, LAGRANGE variable and then use the additional p-level
    // to solve with quadratic elements. Note: set_p_level(1) actually
    // _increases_ the existing variable order by 1, it does not set
    // it to 1.
    for (auto & elem : mesh.active_element_ptr_range())
      elem->set_p_level(1);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    unsigned int u_var = sys.add_variable("u", FIRST, LAGRANGE);

    es.init();
    sys.project_solution(projection_function, nullptr, es.parameters);

    std::unique_ptr<NumericVector<Number>> mesh_function_vector
      = NumericVector<Number>::build(sys.comm());
    mesh_function_vector->init(sys.n_dofs(), sys.n_local_dofs(),
                               sys.get_dof_map().get_send_list(), false,
                               GHOSTED);

    sys.solution->localize(*mesh_function_vector,
                           sys.get_dof_map().get_send_list());

    // So the MeshFunction knows which variables to compute values for.
    std::vector<unsigned int> variables(1);
    variables[0] = u_var;

    auto mesh_function =
      libmesh_make_unique<MeshFunction>(sys.get_equation_systems(),
                                        *mesh_function_vector,
                                        sys.get_dof_map(),
                                        variables);

    mesh_function->init();
    mesh_function->set_point_locator_tolerance(0.0001);
    DenseVector<Number> vec_values;
    std::string dummy;

    // Make sure the MeshFunction's values interpolate the projected solution
    // at the nodes
    for (const auto & node : mesh.local_node_ptr_range())
      {
        (*mesh_function)(*node, /*time=*/ 0., vec_values);
        Real mesh_function_value = projection_function(*node,
                                                       es.parameters,
                                                       dummy,
                                                       dummy);

        CPPUNIT_ASSERT_DOUBLES_EQUAL(vec_values(0), mesh_function_value, TOLERANCE*TOLERANCE);
      }
  }
};

CPPUNIT_TEST_SUITE_REGISTRATION( MeshFunctionTest );
<commit_msg>Skip unit test when !LIBMESH_ENABLE_AMR.<commit_after>// Ignore unused parameter warnings coming from cppunit headers
#include <libmesh/ignore_warnings.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <libmesh/restore_warnings.h>

#include <libmesh/equation_systems.h>
#include <libmesh/replicated_mesh.h>
#include <libmesh/mesh_generation.h>
#include <libmesh/dof_map.h>
#include <libmesh/system.h>
#include <libmesh/mesh_function.h>
#include <libmesh/numeric_vector.h>
#include <libmesh/elem.h>

#include "test_comm.h"

// THE CPPUNIT_TEST_SUITE_END macro expands to code that involves
// std::auto_ptr, which in turn produces -Wdeprecated-declarations
// warnings.  These can be ignored in GCC as long as we wrap the
// offending code in appropriate pragmas.  We can't get away with a
// single ignore_warnings.h inclusion at the beginning of this file,
// since the libmesh headers pull in a restore_warnings.h at some
// point.  We also don't bother restoring warnings at the end of this
// file since it's not a header.
#include <libmesh/ignore_warnings.h>

using namespace libMesh;

Number projection_function (const Point & p,
                            const Parameters &,
                            const std::string &,
                            const std::string &)
{
  return
    cos(.5*libMesh::pi*p(0)) *
    sin(.5*libMesh::pi*p(1)) *
    cos(.5*libMesh::pi*p(2));
}

class MeshFunctionTest : public CppUnit::TestCase
{
  /**
   * Tests for general MeshFunction capability.
   */
public:
  CPPUNIT_TEST_SUITE( MeshFunctionTest );

#if LIBMESH_DIM > 1
#ifdef LIBMESH_ENABLE_AMR
  CPPUNIT_TEST( test_p_level );
#endif
#endif

  CPPUNIT_TEST_SUITE_END();

protected:

public:
  void setUp() {}

  void tearDown() {}

  // test that mesh function works correctly with non-zero
  // Elem::p_level() values.
#ifdef LIBMESH_ENABLE_AMR
  void test_p_level()
  {
    ReplicatedMesh mesh(*TestCommWorld);

    MeshTools::Generation::build_cube (mesh,
                                       5, 5, 5,
                                       0., 1.,
                                       0., 1.,
                                       0., 1.,
                                       HEX20);

    // Bump the p-level for all elements. We will create a system with
    // a FIRST, LAGRANGE variable and then use the additional p-level
    // to solve with quadratic elements. Note: set_p_level(1) actually
    // _increases_ the existing variable order by 1, it does not set
    // it to 1.
    for (auto & elem : mesh.active_element_ptr_range())
      elem->set_p_level(1);

    EquationSystems es(mesh);
    System & sys = es.add_system<System> ("SimpleSystem");
    unsigned int u_var = sys.add_variable("u", FIRST, LAGRANGE);

    es.init();
    sys.project_solution(projection_function, nullptr, es.parameters);

    std::unique_ptr<NumericVector<Number>> mesh_function_vector
      = NumericVector<Number>::build(sys.comm());
    mesh_function_vector->init(sys.n_dofs(), sys.n_local_dofs(),
                               sys.get_dof_map().get_send_list(), false,
                               GHOSTED);

    sys.solution->localize(*mesh_function_vector,
                           sys.get_dof_map().get_send_list());

    // So the MeshFunction knows which variables to compute values for.
    std::vector<unsigned int> variables(1);
    variables[0] = u_var;

    auto mesh_function =
      libmesh_make_unique<MeshFunction>(sys.get_equation_systems(),
                                        *mesh_function_vector,
                                        sys.get_dof_map(),
                                        variables);

    mesh_function->init();
    mesh_function->set_point_locator_tolerance(0.0001);
    DenseVector<Number> vec_values;
    std::string dummy;

    // Make sure the MeshFunction's values interpolate the projected solution
    // at the nodes
    for (const auto & node : mesh.local_node_ptr_range())
      {
        (*mesh_function)(*node, /*time=*/ 0., vec_values);
        Real mesh_function_value = projection_function(*node,
                                                       es.parameters,
                                                       dummy,
                                                       dummy);

        CPPUNIT_ASSERT_DOUBLES_EQUAL(vec_values(0), mesh_function_value, TOLERANCE*TOLERANCE);
      }
  }
#endif // LIBMESH_ENABLE_AMR
};

CPPUNIT_TEST_SUITE_REGISTRATION( MeshFunctionTest );
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

// Warning: order of those include is important.
#include <QDebug>
#include <QApplication>
#include <QResizeEvent>
#include <QPainter>
#include <QBitmap>
#include <QStyle>
#include <QScreen>

#include "../panel/lxqtpanel.h"
#include "trayicon.h"
#include "xfitman.h"

#include <QX11Info>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>

#define XEMBED_EMBEDDED_NOTIFY 0

static bool xError;

/************************************************

************************************************/
int windowErrorHandler(Display *d, XErrorEvent *e)
{
    xError = true;
    if (e->error_code != BadWindow) {
        char str[1024];
        XGetErrorText(d, e->error_code,  str, 1024);
        qWarning() << "Error handler" << e->error_code
                   << str;
    }
    return 0;
}

/************************************************

 ************************************************/
TrayIcon::TrayIcon(Window iconId, QWidget* parent):
    QFrame(parent),
    mIconId(iconId),
    mWindowId(0),
    mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT),
    mDamage(0),
    mDisplay(QX11Info::display())
{
    // NOTE:
    // it's a good idea to save the return value of QX11Info::display().
    // In Qt 5, this API is slower and has some limitations which can trigger crashes.
    // The XDisplay value is actally stored in QScreen object of the primary screen rather than
    // in a global variable. So when the parimary QScreen is being deleted and becomes invalid,
    // QX11Info::display() will fail and cause crash. Storing this value improves the efficiency and
    // also prevent potential crashes caused by this bug.

    setObjectName("TrayIcon");
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    mValid = init();
}

/************************************************

 ************************************************/
bool TrayIcon::init()
{
    Display* dsp = mDisplay;

    XWindowAttributes attr;
    if (! XGetWindowAttributes(dsp, mIconId, &attr)) return false;

//    qDebug() << "New tray icon ***********************************";
//    qDebug() << "  * window id:  " << hex << mIconId;
//    qDebug() << "  * window name:" << xfitMan().getName(mIconId);
//    qDebug() << "  * size (WxH): " << attr.width << "x" << attr.height;
//    qDebug() << "  * color depth:" << attr.depth;

    unsigned long mask = 0;
    XSetWindowAttributes set_attr;

    Visual* visual = attr.visual;
    set_attr.colormap = attr.colormap;
    set_attr.background_pixel = 0;
    set_attr.border_pixel = 0;
    mask = CWColormap|CWBackPixel|CWBorderPixel;

    mWindowId = XCreateWindow(dsp, this->winId(), 0, 0, mIconSize.width(), mIconSize.height(),
                              0, attr.depth, InputOutput, visual, mask, &set_attr);

    xError = false;
    XErrorHandler old;
    old = XSetErrorHandler(windowErrorHandler);
    XReparentWindow(dsp, mIconId, mWindowId, 0, 0);
    XSync(dsp, false);
    XSetErrorHandler(old);

    if (xError)
    {
        qWarning() << "****************************************";
        qWarning() << "* Not icon_swallow                     *";
        qWarning() << "****************************************";
        XDestroyWindow(dsp, mWindowId);
        return false;
    }

    {
        Atom acttype;
        int actfmt;
        unsigned long nbitem, bytes;
        unsigned char *data = 0;
        int ret;

        ret = XGetWindowProperty(dsp, mIconId, xfitMan().atom("_XEMBED_INFO"),
                                 0, 2, false, xfitMan().atom("_XEMBED_INFO"),
                                 &acttype, &actfmt, &nbitem, &bytes, &data);
        if (ret == Success)
        {
            if (data)
                XFree(data);
        }
        else
        {
            qWarning() << "TrayIcon: xembed error";
            XDestroyWindow(dsp, mWindowId);
            return false;
        }
    }

    {
        XEvent e;
        e.xclient.type = ClientMessage;
        e.xclient.serial = 0;
        e.xclient.send_event = True;
        e.xclient.message_type = xfitMan().atom("_XEMBED");
        e.xclient.window = mIconId;
        e.xclient.format = 32;
        e.xclient.data.l[0] = CurrentTime;
        e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY;
        e.xclient.data.l[2] = 0;
        e.xclient.data.l[3] = mWindowId;
        e.xclient.data.l[4] = 0;
        XSendEvent(dsp, mIconId, false, 0xFFFFFF, &e);
    }

    XSelectInput(dsp, mIconId, StructureNotifyMask);
    mDamage = XDamageCreate(dsp, mIconId, XDamageReportRawRectangles);
    XCompositeRedirectWindow(dsp, mWindowId, CompositeRedirectManual);

    XMapWindow(dsp, mIconId);
    XMapRaised(dsp, mWindowId);

    XResizeWindow(dsp, mWindowId, mIconSize.width(), mIconSize.height());
    XResizeWindow(dsp, mIconId, mIconSize.width(), mIconSize.height());

    return true;
}

/************************************************

 ************************************************/
TrayIcon::~TrayIcon()
{
    Display* dsp = mDisplay;
    XSelectInput(dsp, mIconId, NoEventMask);

    if (mDamage)
        XDamageDestroy(dsp, mDamage);

    // reparent to root
    xError = false;
    XErrorHandler old = XSetErrorHandler(windowErrorHandler);

    XUnmapWindow(dsp, mIconId);
    XReparentWindow(dsp, mIconId, QX11Info::appRootWindow(), 0, 0);

    XDestroyWindow(dsp, mWindowId);
    XSync(dsp, False);
    XSetErrorHandler(old);
}

/************************************************

 ************************************************/
QSize TrayIcon::sizeHint() const
{
    QMargins margins = contentsMargins();
    return QSize(margins.left() + mIconSize.width() + margins.right(),
                 margins.top() + mIconSize.height() + margins.bottom()
                );
}

/************************************************

 ************************************************/
void TrayIcon::setIconSize(QSize iconSize)
{
    mIconSize = iconSize;

    if (mWindowId)
        xfitMan().resizeWindow(mWindowId, mIconSize.width(), mIconSize.height());

    if (mIconId)
        xfitMan().resizeWindow(mIconId,   mIconSize.width(), mIconSize.height());
}

/************************************************

 ************************************************/
bool TrayIcon::event(QEvent *event)
{
    switch (event->type())
    {
    case QEvent::Paint:
        draw(static_cast<QPaintEvent*>(event));
        break;

    case QEvent::Resize:
    {
        QRect rect = iconGeometry();
        xfitMan().moveWindow(mWindowId, rect.left(), rect.top());
    }
        break;

    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick:
        event->accept();
        break;

    default:
        break;
    }

    return QFrame::event(event);
}

/************************************************

 ************************************************/
QRect TrayIcon::iconGeometry()
{
    QRect res = QRect(QPoint(0, 0), mIconSize);

    res.moveCenter(QRect(0, 0, width(), height()).center());
    return res;
}

/************************************************

 ************************************************/
void TrayIcon::draw(QPaintEvent* /*event*/)
{
    Display* dsp = mDisplay;

    XWindowAttributes attr;
    if (!XGetWindowAttributes(dsp, mIconId, &attr))
    {
        qWarning() << "Paint error";
        return;
    }

    QImage image;
    XImage* ximage = XGetImage(dsp, mIconId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
    if(ximage)
    {
        image = QImage((const uchar*) ximage->data, ximage->width, ximage->height, ximage->bytes_per_line,  QImage::Format_ARGB32_Premultiplied);
    }
    else
    {
        qWarning() << "    * Error image is NULL";

        XClearArea(mDisplay, (Window)winId(), 0, 0, attr.width, attr.height, False);
        // for some unknown reason, XGetImage failed. try another less efficient method.
        // QScreen::grabWindow uses XCopyArea() internally.
        image = qApp->primaryScreen()->grabWindow(mIconId).toImage();
    }

//    qDebug() << "Paint icon **************************************";
//    qDebug() << "  * XComposite: " << isXCompositeAvailable();
//    qDebug() << "  * Icon geometry:" << iconGeometry();
//    qDebug() << "  Icon";
//    qDebug() << "    * window id:  " << hex << mIconId;
//    qDebug() << "    * window name:" << xfitMan().getName(mIconId);
//    qDebug() << "    * size (WxH): " << attr.width << "x" << attr.height;
//    qDebug() << "    * pos (XxY):  " << attr.x << attr.y;
//    qDebug() << "    * color depth:" << attr.depth;
//    qDebug() << "  XImage";
//    qDebug() << "    * size (WxH):  " << ximage->width << "x" << ximage->height;
//    switch (ximage->format)
//    {
//        case XYBitmap: qDebug() << "    * format:   XYBitmap"; break;
//        case XYPixmap: qDebug() << "    * format:   XYPixmap"; break;
//        case ZPixmap:  qDebug() << "    * format:   ZPixmap"; break;
//    }
//    qDebug() << "    * color depth:  " << ximage->depth;
//    qDebug() << "    * bits per pixel:" << ximage->bits_per_pixel;

    // Draw QImage ...........................
    QPainter painter(this);
    QRect iconRect = iconGeometry();
    if (image.size() != iconRect.size())
    {
        image = image.scaled(iconRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QRect r = image.rect();
        r.moveCenter(iconRect.center());
        iconRect = r;
    }
//    qDebug() << " Draw rect:" << iconRect;

    painter.drawImage(iconRect, image);

    if(ximage)
        XDestroyImage(ximage);
//    debug << "End paint icon **********************************";
}

/************************************************

 ************************************************/
bool TrayIcon::isXCompositeAvailable()
{
    int eventBase, errorBase;
    return XCompositeQueryExtension(QX11Info::display(), &eventBase, &errorBase );
}
<commit_msg>plugin-tray: Fix native window sizes for high DPI devices<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

// Warning: order of those include is important.
#include <QDebug>
#include <QApplication>
#include <QResizeEvent>
#include <QPainter>
#include <QBitmap>
#include <QStyle>
#include <QScreen>

#include "../panel/lxqtpanel.h"
#include "trayicon.h"
#include "xfitman.h"

#include <QX11Info>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>

#define XEMBED_EMBEDDED_NOTIFY 0

static bool xError;

/************************************************

************************************************/
int windowErrorHandler(Display *d, XErrorEvent *e)
{
    xError = true;
    if (e->error_code != BadWindow) {
        char str[1024];
        XGetErrorText(d, e->error_code,  str, 1024);
        qWarning() << "Error handler" << e->error_code
                   << str;
    }
    return 0;
}

/************************************************

 ************************************************/
TrayIcon::TrayIcon(Window iconId, QWidget* parent):
    QFrame(parent),
    mIconId(iconId),
    mWindowId(0),
    mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT),
    mDamage(0),
    mDisplay(QX11Info::display())
{
    // NOTE:
    // it's a good idea to save the return value of QX11Info::display().
    // In Qt 5, this API is slower and has some limitations which can trigger crashes.
    // The XDisplay value is actally stored in QScreen object of the primary screen rather than
    // in a global variable. So when the parimary QScreen is being deleted and becomes invalid,
    // QX11Info::display() will fail and cause crash. Storing this value improves the efficiency and
    // also prevent potential crashes caused by this bug.

    setObjectName("TrayIcon");
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    mValid = init();
}

/************************************************

 ************************************************/
bool TrayIcon::init()
{
    Display* dsp = mDisplay;

    XWindowAttributes attr;
    if (! XGetWindowAttributes(dsp, mIconId, &attr)) return false;

//    qDebug() << "New tray icon ***********************************";
//    qDebug() << "  * window id:  " << hex << mIconId;
//    qDebug() << "  * window name:" << xfitMan().getName(mIconId);
//    qDebug() << "  * size (WxH): " << attr.width << "x" << attr.height;
//    qDebug() << "  * color depth:" << attr.depth;

    unsigned long mask = 0;
    XSetWindowAttributes set_attr;

    Visual* visual = attr.visual;
    set_attr.colormap = attr.colormap;
    set_attr.background_pixel = 0;
    set_attr.border_pixel = 0;
    mask = CWColormap|CWBackPixel|CWBorderPixel;

    mWindowId = XCreateWindow(dsp, this->winId(), 0, 0, mIconSize.width() * metric(PdmDevicePixelRatio), mIconSize.height() * metric(PdmDevicePixelRatio),
                              0, attr.depth, InputOutput, visual, mask, &set_attr);

    xError = false;
    XErrorHandler old;
    old = XSetErrorHandler(windowErrorHandler);
    XReparentWindow(dsp, mIconId, mWindowId, 0, 0);
    XSync(dsp, false);
    XSetErrorHandler(old);

    if (xError)
    {
        qWarning() << "****************************************";
        qWarning() << "* Not icon_swallow                     *";
        qWarning() << "****************************************";
        XDestroyWindow(dsp, mWindowId);
        return false;
    }

    {
        Atom acttype;
        int actfmt;
        unsigned long nbitem, bytes;
        unsigned char *data = 0;
        int ret;

        ret = XGetWindowProperty(dsp, mIconId, xfitMan().atom("_XEMBED_INFO"),
                                 0, 2, false, xfitMan().atom("_XEMBED_INFO"),
                                 &acttype, &actfmt, &nbitem, &bytes, &data);
        if (ret == Success)
        {
            if (data)
                XFree(data);
        }
        else
        {
            qWarning() << "TrayIcon: xembed error";
            XDestroyWindow(dsp, mWindowId);
            return false;
        }
    }

    {
        XEvent e;
        e.xclient.type = ClientMessage;
        e.xclient.serial = 0;
        e.xclient.send_event = True;
        e.xclient.message_type = xfitMan().atom("_XEMBED");
        e.xclient.window = mIconId;
        e.xclient.format = 32;
        e.xclient.data.l[0] = CurrentTime;
        e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY;
        e.xclient.data.l[2] = 0;
        e.xclient.data.l[3] = mWindowId;
        e.xclient.data.l[4] = 0;
        XSendEvent(dsp, mIconId, false, 0xFFFFFF, &e);
    }

    XSelectInput(dsp, mIconId, StructureNotifyMask);
    mDamage = XDamageCreate(dsp, mIconId, XDamageReportRawRectangles);
    XCompositeRedirectWindow(dsp, mWindowId, CompositeRedirectManual);

    XMapWindow(dsp, mIconId);
    XMapRaised(dsp, mWindowId);

    const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)};
    XResizeWindow(dsp, mWindowId, req_size.width(), req_size.height());
    XResizeWindow(dsp, mIconId, req_size.width(), req_size.height());

    return true;
}

/************************************************

 ************************************************/
TrayIcon::~TrayIcon()
{
    Display* dsp = mDisplay;
    XSelectInput(dsp, mIconId, NoEventMask);

    if (mDamage)
        XDamageDestroy(dsp, mDamage);

    // reparent to root
    xError = false;
    XErrorHandler old = XSetErrorHandler(windowErrorHandler);

    XUnmapWindow(dsp, mIconId);
    XReparentWindow(dsp, mIconId, QX11Info::appRootWindow(), 0, 0);

    XDestroyWindow(dsp, mWindowId);
    XSync(dsp, False);
    XSetErrorHandler(old);
}

/************************************************

 ************************************************/
QSize TrayIcon::sizeHint() const
{
    QMargins margins = contentsMargins();
    return QSize(margins.left() + mIconSize.width() + margins.right(),
                 margins.top() + mIconSize.height() + margins.bottom()
                );
}

/************************************************

 ************************************************/
void TrayIcon::setIconSize(QSize iconSize)
{
    mIconSize = iconSize;

    const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)};
    if (mWindowId)
        xfitMan().resizeWindow(mWindowId, req_size.width(), req_size.height());

    if (mIconId)
        xfitMan().resizeWindow(mIconId, req_size.width(), req_size.height());
}

/************************************************

 ************************************************/
bool TrayIcon::event(QEvent *event)
{
    switch (event->type())
    {
    case QEvent::Paint:
        draw(static_cast<QPaintEvent*>(event));
        break;

    case QEvent::Resize:
    {
        QRect rect = iconGeometry();
        xfitMan().moveWindow(mWindowId, rect.left(), rect.top());
    }
        break;

    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick:
        event->accept();
        break;

    default:
        break;
    }

    return QFrame::event(event);
}

/************************************************

 ************************************************/
QRect TrayIcon::iconGeometry()
{
    QRect res = QRect(QPoint(0, 0), mIconSize);

    res.moveCenter(QRect(0, 0, width(), height()).center());
    return res;
}

/************************************************

 ************************************************/
void TrayIcon::draw(QPaintEvent* /*event*/)
{
    Display* dsp = mDisplay;

    XWindowAttributes attr;
    if (!XGetWindowAttributes(dsp, mIconId, &attr))
    {
        qWarning() << "Paint error";
        return;
    }

    QImage image;
    XImage* ximage = XGetImage(dsp, mIconId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap);
    if(ximage)
    {
        image = QImage((const uchar*) ximage->data, ximage->width, ximage->height, ximage->bytes_per_line,  QImage::Format_ARGB32_Premultiplied);
    }
    else
    {
        qWarning() << "    * Error image is NULL";

        XClearArea(mDisplay, (Window)winId(), 0, 0, attr.width, attr.height, False);
        // for some unknown reason, XGetImage failed. try another less efficient method.
        // QScreen::grabWindow uses XCopyArea() internally.
        image = qApp->primaryScreen()->grabWindow(mIconId).toImage();
    }

//    qDebug() << "Paint icon **************************************";
//    qDebug() << "  * XComposite: " << isXCompositeAvailable();
//    qDebug() << "  * Icon geometry:" << iconGeometry();
//    qDebug() << "  Icon";
//    qDebug() << "    * window id:  " << hex << mIconId;
//    qDebug() << "    * window name:" << xfitMan().getName(mIconId);
//    qDebug() << "    * size (WxH): " << attr.width << "x" << attr.height;
//    qDebug() << "    * pos (XxY):  " << attr.x << attr.y;
//    qDebug() << "    * color depth:" << attr.depth;
//    qDebug() << "  XImage";
//    qDebug() << "    * size (WxH):  " << ximage->width << "x" << ximage->height;
//    switch (ximage->format)
//    {
//        case XYBitmap: qDebug() << "    * format:   XYBitmap"; break;
//        case XYPixmap: qDebug() << "    * format:   XYPixmap"; break;
//        case ZPixmap:  qDebug() << "    * format:   ZPixmap"; break;
//    }
//    qDebug() << "    * color depth:  " << ximage->depth;
//    qDebug() << "    * bits per pixel:" << ximage->bits_per_pixel;

    // Draw QImage ...........................
    QPainter painter(this);
    QRect iconRect = iconGeometry();
    if (image.size() != iconRect.size())
    {
        image = image.scaled(iconRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QRect r = image.rect();
        r.moveCenter(iconRect.center());
        iconRect = r;
    }
//    qDebug() << " Draw rect:" << iconRect;

    painter.drawImage(iconRect, image);

    if(ximage)
        XDestroyImage(ximage);
//    debug << "End paint icon **********************************";
}

/************************************************

 ************************************************/
bool TrayIcon::isXCompositeAvailable()
{
    int eventBase, errorBase;
    return XCompositeQueryExtension(QX11Info::display(), &eventBase, &errorBase );
}
<|endoftext|>


<commit_before>/******************************************************************
 *
 * uEcho for C
 *
 * Copyright (C) Satoshi Konno 2015
 *
 * This is licensed under BSD-style license, see file COPYING.
 *
 ******************************************************************/

#include <boost/test/unit_test.hpp>

#include <uecho/controller_internal.h>
#include <uecho/util/timer.h>

#include "TestDevice.h"

BOOST_AUTO_TEST_CASE(ControllerRun)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK(!uecho_controller_getuserdata(ctrl));

  BOOST_CHECK(uecho_controller_start(ctrl));
  BOOST_CHECK(uecho_controller_stop(ctrl));

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerTID)
{
  uEchoController* ctrl = uecho_controller_new();

  uEchoTID first_tid = uecho_controller_getnexttid(ctrl);
  BOOST_CHECK(uEchoTidMin <= first_tid);
  BOOST_CHECK(first_tid <= uEchoTidMax);

  uEchoTID prev_tid = first_tid;
  for (int n = 0; n < 100; n++) {
    uEchoTID tid = uecho_controller_getnexttid(ctrl);
    BOOST_CHECK(uEchoTidMin <= tid);
    BOOST_CHECK(prev_tid < tid);
    BOOST_CHECK(tid <= uEchoTidMax);
  }

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerOption)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoOptionNone), false);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), false);

  uecho_controller_enableoption(ctrl, uEchoControllerOptionDisableUdpServer);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), true);

  uecho_controller_disableoption(ctrl, uEchoControllerOptionDisableUdpServer);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), false);

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerUdpOption)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), true);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), true);

  uecho_controller_disableudpserver(ctrl);
  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), false);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), false);

  uecho_controller_enableudpserver(ctrl);
  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), true);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), true);

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerSearchAll)
{
  // Create Controller (Disable UDP Server)

  uEchoController* ctrl = uecho_controller_new();
  uecho_controller_disableudpserver(ctrl);
  BOOST_CHECK(uecho_controller_start(ctrl));
  BOOST_CHECK(uecho_controller_isrunning(ctrl));

  // Start Device

  uEchoNode* node = uecho_test_createtestnode();
  BOOST_CHECK(uecho_node_start(node));

  // Search (NotificationRequest instead of ReadRequest)

  BOOST_CHECK(uecho_controller_searchallobjectswithesv(ctrl, uEchoEsvNotificationRequest));

  // Find device

  uEchoObject* found_obj = uecho_controller_getobjectbycodewithwait(ctrl, UECHO_TEST_OBJECTCODE, UECHO_TEST_RESPONSE_WAIT_MAX_MTIME);
  BOOST_CHECK(found_obj);

  // Teminate

  BOOST_CHECK(uecho_controller_stop(ctrl));
  uecho_controller_delete(ctrl);

  BOOST_CHECK(uecho_node_stop(node));
  uecho_node_delete(node);
}
<commit_msg>Update ControllerRequest()<commit_after>/******************************************************************
 *
 * uEcho for C
 *
 * Copyright (C) Satoshi Konno 2015
 *
 * This is licensed under BSD-style license, see file COPYING.
 *
 ******************************************************************/

#include <boost/test/unit_test.hpp>

#include <uecho/controller_internal.h>
#include <uecho/util/timer.h>

#include "TestDevice.h"

BOOST_AUTO_TEST_CASE(ControllerRun)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK(!uecho_controller_getuserdata(ctrl));

  BOOST_CHECK(uecho_controller_start(ctrl));
  BOOST_CHECK(uecho_controller_stop(ctrl));

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerTID)
{
  uEchoController* ctrl = uecho_controller_new();

  uEchoTID first_tid = uecho_controller_getnexttid(ctrl);
  BOOST_CHECK(uEchoTidMin <= first_tid);
  BOOST_CHECK(first_tid <= uEchoTidMax);

  uEchoTID prev_tid = first_tid;
  for (int n = 0; n < 100; n++) {
    uEchoTID tid = uecho_controller_getnexttid(ctrl);
    BOOST_CHECK(uEchoTidMin <= tid);
    BOOST_CHECK(prev_tid < tid);
    BOOST_CHECK(tid <= uEchoTidMax);
  }

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerOption)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoOptionNone), false);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), false);

  uecho_controller_enableoption(ctrl, uEchoControllerOptionDisableUdpServer);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), true);

  uecho_controller_disableoption(ctrl, uEchoControllerOptionDisableUdpServer);
  BOOST_CHECK_EQUAL(uecho_controller_isoptionenabled(ctrl, uEchoControllerOptionDisableUdpServer), false);

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerUdpOption)
{
  uEchoController* ctrl = uecho_controller_new();

  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), true);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), true);

  uecho_controller_disableudpserver(ctrl);
  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), false);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), false);

  uecho_controller_enableudpserver(ctrl);
  BOOST_CHECK_EQUAL(uecho_controller_isudpserverenabled(ctrl), true);
  BOOST_CHECK_EQUAL(uecho_server_isudpserverenabled(ctrl->node->server), true);

  uecho_controller_delete(ctrl);
}

BOOST_AUTO_TEST_CASE(ControllerRequest)
{
  // Create Controller (Disable UDP Server)

  uEchoController* ctrl = uecho_controller_new();
  BOOST_CHECK(uecho_controller_start(ctrl));
  BOOST_CHECK(uecho_controller_isrunning(ctrl));

  // Add Device

  uEchoNode* node = uecho_controller_getlocalnode(ctrl);
  uEchoObject* dev = uecho_test_createtestdevice();
  BOOST_CHECK(uecho_node_addobject(node, dev));

  // Search (NotificationRequest instead of ReadRequest)

  BOOST_CHECK(uecho_controller_searchallobjectswithesv(ctrl, uEchoEsvNotificationRequest));

  // Find device

  uEchoObject* found_obj = uecho_controller_getobjectbycodewithwait(ctrl, UECHO_TEST_OBJECTCODE, UECHO_TEST_RESPONSE_WAIT_MAX_MTIME);
  BOOST_CHECK(found_obj);

  // Post Message (ReadRequest)

  uEchoMessage* msg = uecho_message_new();
  uecho_message_setesv(msg, uEchoEsvReadRequest);
  BOOST_CHECK(uecho_message_setproperty(msg, UECHO_TEST_PROPERTY_SWITCHCODE, 0, NULL));

  uEchoMessage* res = uecho_message_new();

  BOOST_CHECK(uecho_controller_postmessage(ctrl, found_obj, msg, res));

  BOOST_CHECK_EQUAL(uecho_message_getopc(res), 1);
  BOOST_CHECK_EQUAL(uecho_message_getesv(res), uEchoEsvReadResponse);
  uEchoProperty* prop = uecho_message_getproperty(res, 0);
  BOOST_CHECK(prop);
  BOOST_CHECK_EQUAL(uecho_property_getcode(prop), UECHO_TEST_PROPERTY_SWITCHCODE);
  BOOST_CHECK_EQUAL(uecho_property_getdatasize(prop), 1);
  byte* prop_data = uecho_property_getdata(prop);
  BOOST_CHECK(prop_data);
  BOOST_CHECK_EQUAL(prop_data[0], UECHO_TEST_PROPERTY_SWITCH_DEFAULT);

  uecho_message_delete(res);
  uecho_message_delete(msg);

  // Post Write Message (WriteRequest:OFF)

  msg = uecho_message_new();
  uecho_message_setesv(msg, uEchoEsvWriteRequestResponseRequired);
  byte post_data[UECHO_TEST_PROPERTY_SWITCH_OFF];
  BOOST_CHECK(uecho_message_setproperty(msg, UECHO_TEST_PROPERTY_SWITCHCODE, 1, post_data));

  res = uecho_message_new();

  BOOST_CHECK(uecho_controller_postmessage(ctrl, found_obj, msg, res));

  BOOST_CHECK_EQUAL(uecho_message_getopc(res), 1);
  BOOST_CHECK_EQUAL(uecho_message_getesv(res), uEchoEsvWriteResponse);
  prop = uecho_message_getproperty(res, 0);
  BOOST_CHECK(prop);
  BOOST_CHECK_EQUAL(uecho_property_getcode(prop), UECHO_TEST_PROPERTY_SWITCHCODE);
  BOOST_CHECK_EQUAL(uecho_property_getdatasize(prop), 0);

  uecho_message_delete(res);
  uecho_message_delete(msg);

  // Post Message (ReadRequest)

  msg = uecho_message_new();
  uecho_message_setesv(msg, uEchoEsvReadRequest);
  BOOST_CHECK(uecho_message_setproperty(msg, UECHO_TEST_PROPERTY_SWITCHCODE, 0, NULL));

  res = uecho_message_new();

  BOOST_CHECK(uecho_controller_postmessage(ctrl, found_obj, msg, res));

  BOOST_CHECK_EQUAL(uecho_message_getopc(res), 1);
  BOOST_CHECK_EQUAL(uecho_message_getesv(res), uEchoEsvReadResponse);
  prop = uecho_message_getproperty(res, 0);
  BOOST_CHECK(prop);
  BOOST_CHECK_EQUAL(uecho_property_getcode(prop), UECHO_TEST_PROPERTY_SWITCHCODE);
  BOOST_CHECK_EQUAL(uecho_property_getdatasize(prop), 1);
  prop_data = uecho_property_getdata(prop);
  BOOST_CHECK(prop_data);
  BOOST_CHECK_EQUAL(prop_data[0], UECHO_TEST_PROPERTY_SWITCH_OFF);

  uecho_message_delete(res);
  uecho_message_delete(msg);

  // Teminate

  BOOST_CHECK(uecho_controller_stop(ctrl));
  uecho_controller_delete(ctrl);
}
<|endoftext|>


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

#include "build/build_config.h"

#if defined(OS_WIN)
#include <objidl.h>
#include <mlang.h>
#endif

#include "config.h"
#include "webkit_version.h"
#pragma warning(push, 0)
#include "BackForwardList.h"
#include "Document.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "Frame.h"
#include "HistoryItem.h"
#if defined(OS_WIN)  // TODO(port): unnecessary after the webkit merge lands.
#include "ImageSource.h"
#endif
#include "KURL.h"
#include "LogWin.h"
#include "Page.h"
#include "PlatformString.h"
#include "RenderTreeAsText.h"
#include "SharedBuffer.h"
#pragma warning(pop)

#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
#include "JSBridge.h"  // for set flags
#endif

#undef LOG
#undef notImplemented
#include "webkit/glue/webkit_glue.h"

#include "base/file_version_info.h"
#include "base/string_util.h"
#include "skia/include/SkBitmap.h"
#include "webkit/glue/event_conversion.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/weburlrequest_impl.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/webview_impl.h"

//------------------------------------------------------------------------------
// webkit_glue impl:

namespace webkit_glue {

void SetJavaScriptFlags(const std::wstring& str) {
#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
  std::string utf8_str = WideToUTF8(str);
  WebCore::JSBridge::setFlags(utf8_str.data(), static_cast<int>(utf8_str.size()));
#endif
}

void SetRecordPlaybackMode(bool value) {
#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
  WebCore::JSBridge::setRecordPlaybackMode(value);
#endif
}

static bool layout_test_mode_ = false;

void SetLayoutTestMode(bool enable) {
  layout_test_mode_ = enable;
}

bool IsLayoutTestMode() {
  return layout_test_mode_;
}

#if defined(OS_WIN)
MONITORINFOEX GetMonitorInfoForWindowHelper(HWND window) {
  HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
  MONITORINFOEX monitorInfo;
  monitorInfo.cbSize = sizeof(MONITORINFOEX);
  GetMonitorInfo(monitor, &monitorInfo);
  return monitorInfo;
}

IMLangFontLink2* GetLangFontLinkHelper() {
  // TODO(hbono): http://b/1072298 Experimentally disabled this code to
  // prevent registry leaks caused by this IMLangFontLink2 interface.
  // If you find any font-rendering regressions. Please feel free to blame me.
  // TODO(hbono): http://b/1072298 The test shell does not use our font metrics
  // but it uses its own font metrics which heavily depend on this
  // IMLangFontLink2 interface. Even though we should change the test shell to
  // use out font metrics and re-baseline such tests, we temporarily let the
  // test shell use this interface until we complete the said change.
  if (!IsLayoutTestMode())
    return NULL;

  static IMultiLanguage *multi_language = NULL;

  if (!multi_language) {
    if (CoCreateInstance(CLSID_CMultiLanguage,
                         0,
                         CLSCTX_ALL,
                         IID_IMultiLanguage,
                         reinterpret_cast<void**>(&multi_language)) != S_OK) {
        return 0;
    }
  }

  static IMLangFontLink2* lang_font_link;
  if (!lang_font_link) {
    if (multi_language->QueryInterface(
            IID_IMLangFontLink2,
            reinterpret_cast<void**>(&lang_font_link)) != S_OK) {
      return 0;
    }
  }

  return lang_font_link;
}
#endif  // defined(OS_WIN)

std::wstring DumpDocumentText(WebFrame* web_frame) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::Frame* frame = webFrameImpl->frame();

  // We use the document element's text instead of the body text here because
  // not all documents have a body, such as XML documents.
  return StringToStdWString(frame->document()->documentElement()->innerText());
}

std::wstring DumpFramesAsText(WebFrame* web_frame, bool recursive) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  std::wstring result;

  // Add header for all but the main frame.
  if (webFrameImpl->GetParent()) {
    result.append(L"\n--------\nFrame: '");
    result.append(webFrameImpl->GetName());
    result.append(L"'\n--------\n");
  }

  result.append(DumpDocumentText(web_frame));
  result.append(L"\n");

  if (recursive) {
    WebCore::Frame* child = webFrameImpl->frame()->tree()->firstChild();
    for (; child; child = child->tree()->nextSibling()) {
      result.append(
          DumpFramesAsText(WebFrameImpl::FromFrame(child), recursive));
    }
  }

  return result;
}

std::wstring DumpRenderer(WebFrame* web_frame) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::Frame* frame = webFrameImpl->frame();

  // This implicitly converts from a DeprecatedString.
  return StringToStdWString(WebCore::externalRepresentation(frame->renderer()));
}

std::wstring DumpFrameScrollPosition(WebFrame* web_frame, bool recursive) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::IntSize offset = webFrameImpl->frameview()->scrollOffset();
  std::wstring result;

  if (offset.width() > 0 || offset.height() > 0) {
    if (webFrameImpl->GetParent()) {
      StringAppendF(&result, L"frame '%ls' ", StringToStdWString(
          webFrameImpl->frame()->tree()->name()).c_str());
    }
    StringAppendF(&result, L"scrolled to %d,%d\n",
                  offset.width(), offset.height());
  }

  if (recursive) {
    WebCore::Frame* child = webFrameImpl->frame()->tree()->firstChild();
    for (; child; child = child->tree()->nextSibling()) {
      result.append(DumpFrameScrollPosition(WebFrameImpl::FromFrame(child),
                                            recursive));
    }
  }

  return result;
}

// Returns True if item1 < item2.
static bool HistoryItemCompareLess(PassRefPtr<WebCore::HistoryItem> item1,
                                   PassRefPtr<WebCore::HistoryItem> item2) {
  std::wstring target1 = StringToStdWString(item1->target());
  std::wstring target2 = StringToStdWString(item2->target());
  std::transform(target1.begin(), target1.end(), target1.begin(), tolower);
  std::transform(target2.begin(), target2.end(), target2.begin(), tolower);
  return target1 < target2;
}

// Writes out a HistoryItem into a string in a readable format.
static void DumpHistoryItem(WebCore::HistoryItem* item, int indent,
                            bool is_current, std::wstring* result) {
  if (is_current) {
    result->append(L"curr->");
    result->append(indent - 6, L' ');  // 6 == L"curr->".length()
  } else {
    result->append(indent, L' ');
  }

  result->append(StringToStdWString(item->urlString()));
  if (!item->target().isEmpty()) {
    result->append(L" (in frame \"" + StringToStdWString(item->target()) +
                   L"\")");
  }
  if (item->isTargetItem())
    result->append(L"  **nav target**");
  result->append(L"\n");

  if (item->hasChildren()) {
    WebCore::HistoryItemVector children = item->children();
    // Must sort to eliminate arbitrary result ordering which defeats
    // reproducible testing.
    std::sort(children.begin(), children.end(), HistoryItemCompareLess);
    for (unsigned i = 0; i < children.size(); i++) {
      DumpHistoryItem(children[i].get(), indent+4, false, result);
    }
  }
}

void DumpBackForwardList(WebView* view, void* previous_history_item,
                         std::wstring* result) {
  result->append(L"\n============== Back Forward List ==============\n");

  WebCore::Frame* frame =
      static_cast<WebFrameImpl*>(view->GetMainFrame())->frame();
  WebCore::BackForwardList* list = frame->page()->backForwardList();

  // Skip everything before the previous_history_item, if it's in the back list.
  // If it isn't found, assume it fell off the end, and include everything.
  int start_index = -list->backListCount();
  WebCore::HistoryItem* prev_item =
      static_cast<WebCore::HistoryItem*>(previous_history_item);
  for (int i = -list->backListCount(); i < 0; ++i) {
    if (prev_item == list->itemAtIndex(i))
      start_index = i+1;
  }

  for (int i = start_index; i < 0; ++i)
    DumpHistoryItem(list->itemAtIndex(i), 8, false, result);

  DumpHistoryItem(list->currentItem(), 8, true, result);

  for (int i = 1; i <= list->forwardListCount(); ++i)
    DumpHistoryItem(list->itemAtIndex(i), 8, false, result);

  result->append(L"===============================================\n");
}

void ResetBeforeTestRun(WebView* view) {
  WebFrameImpl* webframe = static_cast<WebFrameImpl*>(view->GetMainFrame());
  WebCore::Frame* frame = webframe->frame();

  // Reset the main frame name since tests always expect it to be empty.  It
  // is normally not reset between page loads (even in IE and FF).
  if (frame && frame->tree())
    frame->tree()->setName("");

  // This is papering over b/850700.  But it passes a few more tests, so we'll
  // keep it for now.
  if (frame && frame->scriptBridge())
    frame->scriptBridge()->setEventHandlerLineno(0);

  // Reset the last click information so the clicks generated from previous
  // test aren't inherited (otherwise can mistake single/double/triple clicks)
  MakePlatformMouseEvent::ResetLastClick();
}

#ifndef NDEBUG
// The log macro was having problems due to collisions with WTF, so we just
// code here what that would have inlined.
void DumpLeakedObject(const char* file, int line, const char* object, int count) {
  std::string msg = StringPrintf("%s LEAKED %d TIMES", object, count);
  AppendToLog(file, line, msg.c_str());
}
#endif

void CheckForLeaks() {
#ifndef NDEBUG
  int count = WebFrameImpl::live_object_count();
  if (count)
    DumpLeakedObject(__FILE__, __LINE__, "WebFrame", count);
#endif
}

bool DecodeImage(const std::string& image_data, SkBitmap* image) {
#if defined(OS_WIN)  // TODO(port): unnecessary after the webkit merge lands.
   RefPtr<WebCore::SharedBuffer> buffer(
       new WebCore::SharedBuffer(image_data.data(),
                                 static_cast<int>(image_data.length())));
  WebCore::ImageSource image_source;
  image_source.setData(buffer.get(), true);

  if (image_source.frameCount() > 0) {
    *image = *reinterpret_cast<SkBitmap*>(image_source.createFrameAtIndex(0));
    return true;
  }
  // We failed to decode the image.
  return false;
#else
  // This ought to work; we just need the webkit merge.
  NOTIMPLEMENTED();
  return false;
#endif
}

// Convert from WebKit types to Glue types and notify the embedder. This should
// not perform complex processing since it may be called a lot.
void NotifyFormStateChanged(const WebCore::Document* document) {
  if (!document)
    return;

  WebCore::Frame* frame = document->frame();
  if (!frame)
    return;

  // Dispatch to the delegate of the view that owns the frame.
  WebFrame* webframe = WebFrameImpl::FromFrame(document->frame());
  WebView* webview = webframe->GetView();
  if (!webview)
    return;
  WebViewDelegate* delegate = webview->GetDelegate();
  if (!delegate)
    return;
  delegate->OnNavStateChanged(webview);
}

std::string GetWebKitVersion() {
  return StringPrintf("%d.%d", WEBKIT_VERSION_MAJOR, WEBKIT_VERSION_MINOR);
}

const std::string& GetDefaultUserAgent() {
#if defined(OS_WIN)
  static std::string user_agent;
  static bool generated_user_agent;
  if (!generated_user_agent) {
    OSVERSIONINFO info = {0};
    info.dwOSVersionInfoSize = sizeof(info);
    GetVersionEx(&info);

    // Get the product name and version, and replace Safari's Version/X string
    // with it.  This is done to expose our product name in a manner that is
    // maximally compatible with Safari, we hope!!
    std::string product;

    FileVersionInfo* version_info =
        FileVersionInfo::CreateFileVersionInfoForCurrentModule();
    if (version_info)
      product = "Chrome/" + WideToASCII(version_info->product_version());

    if (product.empty())
      product = "Version/3.1";

    // Derived from Safari's UA string.
    StringAppendF(
        &user_agent,
        "Mozilla/5.0 (Windows; U; Windows NT %d.%d; en-US) AppleWebKit/%d.%d"
        " (KHTML, like Gecko) %s Safari/%d.%d",
        info.dwMajorVersion,
        info.dwMinorVersion,
        WEBKIT_VERSION_MAJOR,
        WEBKIT_VERSION_MINOR,
        product.c_str(),
        WEBKIT_VERSION_MAJOR,
        WEBKIT_VERSION_MINOR
        );

    generated_user_agent = true;
  }

  return user_agent;
#else
  // TODO(port): we need something like FileVersionInfo for our UA string.
  NOTIMPLEMENTED();
  return EmptyString();
#endif
}

void NotifyJSOutOfMemory(WebCore::Frame* frame) {
  if (!frame)
    return;

  // Dispatch to the delegate of the view that owns the frame.
  WebFrame* webframe = WebFrameImpl::FromFrame(frame);
  WebView* webview = webframe->GetView();
  if (!webview)
    return;
  WebViewDelegate* delegate = webview->GetDelegate();
  if (!delegate)
    return;
  delegate->JSOutOfMemory();
}

} // namespace webkit_glue
<commit_msg>stub out win-only routines and impl user agent for MacOS X Review URL: http://codereview.chromium.org/262<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <objidl.h>
#include <mlang.h>
#endif

#include "config.h"
#include "webkit_version.h"
#pragma warning(push, 0)
#include "BackForwardList.h"
#include "Document.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "Frame.h"
#include "HistoryItem.h"
#if defined(OS_WIN)  // TODO(port): unnecessary after the webkit merge lands.
#include "ImageSource.h"
#endif
#include "KURL.h"
#include "LogWin.h"
#include "Page.h"
#include "PlatformString.h"
#include "RenderTreeAsText.h"
#include "SharedBuffer.h"
#pragma warning(pop)

#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
#include "JSBridge.h"  // for set flags
#endif

#undef LOG
#undef notImplemented
#include "webkit/glue/webkit_glue.h"

#include "base/file_version_info.h"
#include "base/string_util.h"
#include "skia/include/SkBitmap.h"
#include "webkit/glue/event_conversion.h"
#include "webkit/glue/glue_util.h"
#include "webkit/glue/weburlrequest_impl.h"
#include "webkit/glue/webframe_impl.h"
#include "webkit/glue/webview_impl.h"

//------------------------------------------------------------------------------
// webkit_glue impl:

namespace webkit_glue {

void SetJavaScriptFlags(const std::wstring& str) {
#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
  std::string utf8_str = WideToUTF8(str);
  WebCore::JSBridge::setFlags(utf8_str.data(), static_cast<int>(utf8_str.size()));
#endif
}

void SetRecordPlaybackMode(bool value) {
#if USE(V8_BINDING) || USE(JAVASCRIPTCORE_BINDINGS)
  WebCore::JSBridge::setRecordPlaybackMode(value);
#endif
}

static bool layout_test_mode_ = false;

void SetLayoutTestMode(bool enable) {
  layout_test_mode_ = enable;
}

bool IsLayoutTestMode() {
  return layout_test_mode_;
}

#if defined(OS_WIN)
MONITORINFOEX GetMonitorInfoForWindowHelper(HWND window) {
  HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
  MONITORINFOEX monitorInfo;
  monitorInfo.cbSize = sizeof(MONITORINFOEX);
  GetMonitorInfo(monitor, &monitorInfo);
  return monitorInfo;
}

IMLangFontLink2* GetLangFontLinkHelper() {
  // TODO(hbono): http://b/1072298 Experimentally disabled this code to
  // prevent registry leaks caused by this IMLangFontLink2 interface.
  // If you find any font-rendering regressions. Please feel free to blame me.
  // TODO(hbono): http://b/1072298 The test shell does not use our font metrics
  // but it uses its own font metrics which heavily depend on this
  // IMLangFontLink2 interface. Even though we should change the test shell to
  // use out font metrics and re-baseline such tests, we temporarily let the
  // test shell use this interface until we complete the said change.
  if (!IsLayoutTestMode())
    return NULL;

  static IMultiLanguage *multi_language = NULL;

  if (!multi_language) {
    if (CoCreateInstance(CLSID_CMultiLanguage,
                         0,
                         CLSCTX_ALL,
                         IID_IMultiLanguage,
                         reinterpret_cast<void**>(&multi_language)) != S_OK) {
        return 0;
    }
  }

  static IMLangFontLink2* lang_font_link;
  if (!lang_font_link) {
    if (multi_language->QueryInterface(
            IID_IMLangFontLink2,
            reinterpret_cast<void**>(&lang_font_link)) != S_OK) {
      return 0;
    }
  }

  return lang_font_link;
}
#endif  // defined(OS_WIN)

std::wstring DumpDocumentText(WebFrame* web_frame) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::Frame* frame = webFrameImpl->frame();

  // We use the document element's text instead of the body text here because
  // not all documents have a body, such as XML documents.
  return StringToStdWString(frame->document()->documentElement()->innerText());
}

std::wstring DumpFramesAsText(WebFrame* web_frame, bool recursive) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  std::wstring result;

  // Add header for all but the main frame.
  if (webFrameImpl->GetParent()) {
    result.append(L"\n--------\nFrame: '");
    result.append(webFrameImpl->GetName());
    result.append(L"'\n--------\n");
  }

  result.append(DumpDocumentText(web_frame));
  result.append(L"\n");

  if (recursive) {
    WebCore::Frame* child = webFrameImpl->frame()->tree()->firstChild();
    for (; child; child = child->tree()->nextSibling()) {
      result.append(
          DumpFramesAsText(WebFrameImpl::FromFrame(child), recursive));
    }
  }

  return result;
}

std::wstring DumpRenderer(WebFrame* web_frame) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::Frame* frame = webFrameImpl->frame();

  // This implicitly converts from a DeprecatedString.
  return StringToStdWString(WebCore::externalRepresentation(frame->renderer()));
}

std::wstring DumpFrameScrollPosition(WebFrame* web_frame, bool recursive) {
  WebFrameImpl* webFrameImpl = static_cast<WebFrameImpl*>(web_frame);
  WebCore::IntSize offset = webFrameImpl->frameview()->scrollOffset();
  std::wstring result;

  if (offset.width() > 0 || offset.height() > 0) {
    if (webFrameImpl->GetParent()) {
      StringAppendF(&result, L"frame '%ls' ", StringToStdWString(
          webFrameImpl->frame()->tree()->name()).c_str());
    }
    StringAppendF(&result, L"scrolled to %d,%d\n",
                  offset.width(), offset.height());
  }

  if (recursive) {
    WebCore::Frame* child = webFrameImpl->frame()->tree()->firstChild();
    for (; child; child = child->tree()->nextSibling()) {
      result.append(DumpFrameScrollPosition(WebFrameImpl::FromFrame(child),
                                            recursive));
    }
  }

  return result;
}

// Returns True if item1 < item2.
static bool HistoryItemCompareLess(PassRefPtr<WebCore::HistoryItem> item1,
                                   PassRefPtr<WebCore::HistoryItem> item2) {
  std::wstring target1 = StringToStdWString(item1->target());
  std::wstring target2 = StringToStdWString(item2->target());
  std::transform(target1.begin(), target1.end(), target1.begin(), tolower);
  std::transform(target2.begin(), target2.end(), target2.begin(), tolower);
  return target1 < target2;
}

// Writes out a HistoryItem into a string in a readable format.
static void DumpHistoryItem(WebCore::HistoryItem* item, int indent,
                            bool is_current, std::wstring* result) {
  if (is_current) {
    result->append(L"curr->");
    result->append(indent - 6, L' ');  // 6 == L"curr->".length()
  } else {
    result->append(indent, L' ');
  }

  result->append(StringToStdWString(item->urlString()));
  if (!item->target().isEmpty()) {
    result->append(L" (in frame \"" + StringToStdWString(item->target()) +
                   L"\")");
  }
  if (item->isTargetItem())
    result->append(L"  **nav target**");
  result->append(L"\n");

  if (item->hasChildren()) {
    WebCore::HistoryItemVector children = item->children();
    // Must sort to eliminate arbitrary result ordering which defeats
    // reproducible testing.
    std::sort(children.begin(), children.end(), HistoryItemCompareLess);
    for (unsigned i = 0; i < children.size(); i++) {
      DumpHistoryItem(children[i].get(), indent+4, false, result);
    }
  }
}

void DumpBackForwardList(WebView* view, void* previous_history_item,
                         std::wstring* result) {
  result->append(L"\n============== Back Forward List ==============\n");

  WebCore::Frame* frame =
      static_cast<WebFrameImpl*>(view->GetMainFrame())->frame();
  WebCore::BackForwardList* list = frame->page()->backForwardList();

  // Skip everything before the previous_history_item, if it's in the back list.
  // If it isn't found, assume it fell off the end, and include everything.
  int start_index = -list->backListCount();
  WebCore::HistoryItem* prev_item =
      static_cast<WebCore::HistoryItem*>(previous_history_item);
  for (int i = -list->backListCount(); i < 0; ++i) {
    if (prev_item == list->itemAtIndex(i))
      start_index = i+1;
  }

  for (int i = start_index; i < 0; ++i)
    DumpHistoryItem(list->itemAtIndex(i), 8, false, result);

  DumpHistoryItem(list->currentItem(), 8, true, result);

  for (int i = 1; i <= list->forwardListCount(); ++i)
    DumpHistoryItem(list->itemAtIndex(i), 8, false, result);

  result->append(L"===============================================\n");
}

void ResetBeforeTestRun(WebView* view) {
  WebFrameImpl* webframe = static_cast<WebFrameImpl*>(view->GetMainFrame());
  WebCore::Frame* frame = webframe->frame();

  // Reset the main frame name since tests always expect it to be empty.  It
  // is normally not reset between page loads (even in IE and FF).
  if (frame && frame->tree())
    frame->tree()->setName("");

  // This is papering over b/850700.  But it passes a few more tests, so we'll
  // keep it for now.
  if (frame && frame->scriptBridge())
    frame->scriptBridge()->setEventHandlerLineno(0);

  // Reset the last click information so the clicks generated from previous
  // test aren't inherited (otherwise can mistake single/double/triple clicks)
  MakePlatformMouseEvent::ResetLastClick();
}

#ifndef NDEBUG
// The log macro was having problems due to collisions with WTF, so we just
// code here what that would have inlined.
void DumpLeakedObject(const char* file, int line, const char* object, int count) {
  std::string msg = StringPrintf("%s LEAKED %d TIMES", object, count);
  AppendToLog(file, line, msg.c_str());
}
#endif

void CheckForLeaks() {
#ifndef NDEBUG
  int count = WebFrameImpl::live_object_count();
  if (count)
    DumpLeakedObject(__FILE__, __LINE__, "WebFrame", count);
#endif
}

bool DecodeImage(const std::string& image_data, SkBitmap* image) {
#if defined(OS_WIN)  // TODO(port): unnecessary after the webkit merge lands.
   RefPtr<WebCore::SharedBuffer> buffer(
       new WebCore::SharedBuffer(image_data.data(),
                                 static_cast<int>(image_data.length())));
  WebCore::ImageSource image_source;
  image_source.setData(buffer.get(), true);

  if (image_source.frameCount() > 0) {
    *image = *reinterpret_cast<SkBitmap*>(image_source.createFrameAtIndex(0));
    return true;
  }
  // We failed to decode the image.
  return false;
#else
  // This ought to work; we just need the webkit merge.
  NOTIMPLEMENTED();
  return false;
#endif
}

// Convert from WebKit types to Glue types and notify the embedder. This should
// not perform complex processing since it may be called a lot.
void NotifyFormStateChanged(const WebCore::Document* document) {
  if (!document)
    return;

  WebCore::Frame* frame = document->frame();
  if (!frame)
    return;

  // Dispatch to the delegate of the view that owns the frame.
  WebFrame* webframe = WebFrameImpl::FromFrame(document->frame());
  WebView* webview = webframe->GetView();
  if (!webview)
    return;
  WebViewDelegate* delegate = webview->GetDelegate();
  if (!delegate)
    return;
  delegate->OnNavStateChanged(webview);
}

std::string GetWebKitVersion() {
  return StringPrintf("%d.%d", WEBKIT_VERSION_MAJOR, WEBKIT_VERSION_MINOR);
}

const std::string& GetDefaultUserAgent() {
#if defined(OS_WIN)
  static std::string user_agent;
  static bool generated_user_agent;
  if (!generated_user_agent) {
    int32 os_major_version = 0;
    int32 os_minor_version = 0;
    int32 os_bugfix_version = 0;
#if defined(OS_WIN)
    OSVERSIONINFO info = {0};
    info.dwOSVersionInfoSize = sizeof(info);
    GetVersionEx(&info);
    os_major_version = info.dwMajorVersion;
    os_minor_version = info.dwMinorVersion;
#elif defined(OS_MACOSX)
    Gestalt(gestaltSystemVersionMajor,
        reinterpret_cast<SInt32*>(&os_major_version));
    Gestalt(gestaltSystemVersionMinor,
        reinterpret_cast<SInt32*>(&os_minor_version));
    Gestalt(gestaltSystemVersionBugFix,
        reinterpret_cast<SInt32*>(&os_bugfix_version));
#endif

    // Get the product name and version, and replace Safari's Version/X string
    // with it.  This is done to expose our product name in a manner that is
    // maximally compatible with Safari, we hope!!
    std::string product;

    FileVersionInfo* version_info =
        FileVersionInfo::CreateFileVersionInfoForCurrentModule();
    if (version_info)
      product = "Chrome/" + WideToASCII(version_info->product_version());

    if (product.empty())
      product = "Version/3.1";

    // Derived from Safari's UA string.
    StringAppendF(
        &user_agent,
#if defined(OS_WIN)
        "Mozilla/5.0 (Windows; U; Windows NT %d.%d; en-US) AppleWebKit/%d.%d"
#elif defined(OS_MACOSX)
        "Mozilla/5.0 (Macintosh; U; Intel Mac OS X %d_%d_%d; en-US) AppleWebKit/%d.%d"
#endif
        " (KHTML, like Gecko) %s Safari/%d.%d",
        os_major_version,
        os_minor_version,
#if defined(OS_MACOSX)
        os_bugfix_version,
#endif
        WEBKIT_VERSION_MAJOR,
        WEBKIT_VERSION_MINOR,
        product.c_str(),
        WEBKIT_VERSION_MAJOR,
        WEBKIT_VERSION_MINOR
        );

    generated_user_agent = true;
  }

  return user_agent;
#else
  // TODO(port): we need something like FileVersionInfo for our UA string.
  NOTIMPLEMENTED();
  return EmptyString();
#endif
}

void NotifyJSOutOfMemory(WebCore::Frame* frame) {
  if (!frame)
    return;

  // Dispatch to the delegate of the view that owns the frame.
  WebFrame* webframe = WebFrameImpl::FromFrame(frame);
  WebView* webview = webframe->GetView();
  if (!webview)
    return;
  WebViewDelegate* delegate = webview->GetDelegate();
  if (!delegate)
    return;
  delegate->JSOutOfMemory();
}

} // namespace webkit_glue
<|endoftext|>