<commit_before>//===========================================================================
//
// File: Identity.C
//
// Created:
//
// Author: Vibeke Skytt
//
// Revision:
//
// Description: Check for identical and embedded entities
//
//===========================================================================

#include "GoTools/intersections/Identity.h"
#include "GoTools/intersections/ParamSurfaceInt.h"
#include "GoTools/intersections/ParamCurveInt.h"
#include "GoTools/intersections/Coincidence.h"
#include "GoTools/intersections/GeoTol.h"

using std::vector;

namespace Go
{
    int Identity::identicalSfs(shared_ptr<ParamSurface> sf1,
			       shared_ptr<ParamSurface> sf2,
			       double tol)
    {
	// Initialize intersection objects
	shared_ptr<ParamSurfaceInt> intsf1 =
	    shared_ptr<ParamSurfaceInt>(new ParamSurfaceInt(sf1));
	shared_ptr<ParamSurfaceInt> intsf2 =
	    shared_ptr<ParamSurfaceInt>(new ParamSurfaceInt(sf2));
	shared_ptr<GeoTol> eps = shared_ptr<GeoTol>(new GeoTol(tol));

	// Fetch boundary elements
	vector<shared_ptr<BoundaryGeomInt> > bd_cvs1;
	vector<shared_ptr<BoundaryGeomInt> > bd_cvs2;

	intsf1->getBoundaryObjects(bd_cvs1);
	intsf2->getBoundaryObjects(bd_cvs2);

	// Check identity of boundary curves
	int ki, kj;
	int coincident = 0;
	double start1, start2, end1, end2;
	for (ki=0; ki<int(bd_cvs1.size()); ++ki)
	{
	    ParamCurveInt *cv1 = bd_cvs1[ki]->getObject()->getParamCurveInt();
	    start1 = cv1->startParam(0);
	    end1 = cv1->endParam(0);
	    for (kj=0; kj<int(bd_cvs2.size()); ++kj)
	    {
		ParamCurveInt *cv2 = bd_cvs2[kj]->getObject()->getParamCurveInt();
		start2 = cv2->startParam(0);
		end2 = cv2->endParam(0);

		// Check orientation
		Point pt1, pt2, pt3, pt4;
		cv1->point(pt1, &start1);
		cv1->point(pt2, &end1);
		cv2->point(pt3, &start2);
		cv2->point(pt4, &end2);
		if (!(pt1.dist(pt3) < tol || pt1.dist(pt4) < tol))
		    continue;
		if (!(pt2.dist(pt3) < tol || pt2.dist(pt4) < tol))
		    continue;
		if (pt1.dist(pt3) < pt1.dist(pt4))
		    coincident = checkCoincide(cv1, start1, end1, eps,
					       cv2, start2, end2);
		else
		    coincident = checkCoincide(cv1, start1, end1, eps,
					       cv2, end2, start2);
		if (coincident)
		    break;
	    }
	    if (kj == int(bd_cvs2.size()))
		break;  // No coincidence for this boundary curve
	}

	if (ki == int(bd_cvs1.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf1, intsf2, eps);
	    if (coincident)
		return 1;
	}

	// Check if the boundary curves of surface 1 lies in surface 2
	for (ki=0; ki<int(bd_cvs1.size()); ++ki)
	{
	    ParamCurveInt *cv1 = bd_cvs1[ki]->getObject()->getParamCurveInt();
	    start1 = cv1->startParam(0);
	    end1 = cv1->endParam(0);

	    // Project the endpoints onto surface 2
	    Point pt1, pt2, clo_pt1, clo_pt2;
	    double u1, v1, u2, v2, dist1, dist2;
	    cv1->point(pt1, &start1);
	    cv1->point(pt2, &end1);
	    sf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    sf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
	    if (dist2 > tol)
		break;  // No coincidence

	    // Check curve
	    coincident = checkCoincide(cv1, start1, end1,
				       intsf2.get(), Point(u1,v1), Point(u2,v2),
				       eps);
	    if (!coincident)
		break;
	}
	if (ki == int(bd_cvs1.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf1, intsf2, eps);
	    if (coincident)
		return 2;
	}

	// Check if the boundary curves of surface 2 lies in surface 1
	for (ki=0; ki<int(bd_cvs2.size()); ++ki)
	{
	    ParamCurveInt *cv2 = bd_cvs2[ki]->getObject()->getParamCurveInt();
	    start2 = cv2->startParam(0);
	    end2 = cv2->endParam(0);

	    // Project the endpoints onto surface 2
	    Point pt1, pt2, clo_pt1, clo_pt2;
	    double u1, v1, u2, v2, dist1, dist2;
	    cv2->point(pt1, &start2);
	    cv2->point(pt2, &end2);
	    sf1->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    sf1->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    // Check curve
	    coincident = checkCoincide(cv2, start2, end2,
				       intsf1.get(), Point(u1,v1), Point(u2,v2),
				       eps);
	    if (!coincident)
		break;
	}
	if (ki == int(bd_cvs2.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf2, intsf1, eps);
	    if (coincident)
		return 3;
	}

	// The surfaces are neither identical nor is one embedded in the other
	return 0;
    }

    int Identity::identicalCvs(shared_ptr<ParamCurve> cv1, double start1, double end1,
			       shared_ptr<ParamCurve> cv2, double start2, double end2,
			       double tol)
	// Check if two curves are identical, or one is embedded in the other.
	// The curve extension is limited by start and end parameters of each curve
    {
	// Box test
	BoundingBox box1 = cv1->boundingBox();
	BoundingBox box2 = cv2->boundingBox();
	if (!box1.overlaps(box2, tol))
	    return 0;

	// Initialize intersection objects
	shared_ptr<ParamCurveInt> intcv1 =
	    shared_ptr<ParamCurveInt>(new ParamCurveInt(cv1));
	shared_ptr<ParamCurveInt> intcv2 =
	    shared_ptr<ParamCurveInt>(new ParamCurveInt(cv2));
	shared_ptr<GeoTol> eps = shared_ptr<GeoTol>(new GeoTol(tol));

	// Check endpoints
	Point pt1, pt2, pt3, pt4;
	intcv1->point(pt1, &start1);
	intcv1->point(pt2, &end1);
	intcv2->point(pt3, &start2);
	intcv2->point(pt4, &end2);

	// First check coincidence
	int coincident = 0;
	if (pt1.dist(pt3) <= tol && pt2.dist(pt4) <= tol)
	    coincident = checkCoincide(intcv1.get(), start1, end1, eps,
				       intcv2.get(), start2, end2);
	else if (pt1.dist(pt4) <= tol && pt2.dist(pt3) <= tol)
	    coincident = checkCoincide(intcv1.get(), start1, end1, eps,
				       intcv2.get(), end2, start2);
	else
	{
	    // Project the endpoints on one curve onto the other curve and
	    // check for embedded curves
	    // First check if the first curve is embedded into the second
	    Point clo_pt1, clo_pt2;
	    double clo_dist1, clo_dist2;
	    double clo_par1, clo_par2;

	    cv2->closestPoint(pt1, start2, end2, clo_par1, clo_pt1, clo_dist1);
	    cv2->closestPoint(pt2, start2, end2, clo_par2, clo_pt2, clo_dist2);
	    if (clo_dist1 <= tol && clo_dist2 <= tol)
	    {
		// Posibility for embedded curve
		coincident = checkCoincide(intcv1.get(), start1, end1, eps,
					   intcv2.get(), clo_par1, clo_par2);
		if (coincident)
		    coincident = 2;
	    }

	    if (!coincident)
	    {
		// Check if curve two is embedded in curve one
		cv1->closestPoint(pt3, start1, end1, clo_par1, clo_pt1, clo_dist1);
		cv2->closestPoint(pt4, start1, end1, clo_par2, clo_pt2, clo_dist2);
		if (clo_dist1 <= tol && clo_dist2 <= tol)
		{
		    // Posibility for embedded curve
		    coincident = checkCoincide(intcv2.get(), start2, end2, eps,
					       intcv1.get(), clo_par1, clo_par2);
		    if (coincident)
			coincident = 3;
		}

	    }
	}

	return coincident;
    }

    int Identity::internalCoincidence(shared_ptr<ParamSurfaceInt>& intsf1,
				      shared_ptr<ParamSurfaceInt>& intsf2,
				      shared_ptr<GeoTol>& eps)
    {
	// Check if the first surface lies in the other.
	// The surface boundaries are already tested

	const RectDomain& domain = intsf1->getDomain();  // Surrounding parameter domain
	double umin = domain.umin();
	double umax = domain.umax();
	double vmin = domain.vmin();
	double vmax = domain.vmax();
	int nmb_sample_crvs = 10;
	double tint1 = (umax - umin)/(int)(nmb_sample_crvs+1);  // Only parameter values in the inner
	double tint2 = (vmax - vmin)/(int)(nmb_sample_crvs+1);

	// Check coincidence with surface 2 along a number of constant parameter curves of
	// surface 1 in both parameter directions
	// 1. parameter direction
	double par;
	int ki, kj;
	int coincident;
	shared_ptr<ParamSurface> surf1 = intsf1->getParamSurface();
	shared_ptr<ParamSurface> surf2 = intsf2->getParamSurface();
	double tol = eps->getEpsge();
	for (ki=0, par=umin+tint1; ki<nmb_sample_crvs; ++ki, par+=tint1)
	{
	    vector<shared_ptr<ParamCurve> > const_crvs = surf1->constParamCurves(par, false);
	    for (kj=0; kj<int(const_crvs.size()); ++kj)
	    {
		shared_ptr<ParamCurveInt> intcrv =
		    shared_ptr<ParamCurveInt>(new ParamCurveInt(const_crvs[kj]));

		// Project the endpoints onto surface 2
		double start, end;
		Point pt1, pt2, clo_pt1, clo_pt2;
		double u1, v1, u2, v2, dist1, dist2;
		start = intcrv->startParam(0);
		end = intcrv->endParam(0);
		intcrv->point(pt1, &start);
		intcrv->point(pt2, &end);
		surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		// Check curve
		coincident = checkCoincide(intcrv.get(), start, end,
					   intsf2.get(), Point(u1,v1), Point(u2,v2),
					   eps);
		if (!coincident)
		    return 0;
	    }
	}

	// 2. parameter direction
	for (ki=0, par=vmin+tint2; ki<nmb_sample_crvs; ++ki, par+=tint2)
	{
	    vector<shared_ptr<ParamCurve> > const_crvs = surf1->constParamCurves(par, true);
	    for (kj=0; kj<int(const_crvs.size()); ++kj)
	    {
		shared_ptr<ParamCurveInt> intcrv =
		    shared_ptr<ParamCurveInt>(new ParamCurveInt(const_crvs[kj]));

		// Project the endpoints onto surface 2
		double start, end;
		Point pt1, pt2, clo_pt1, clo_pt2;
		double u1, v1, u2, v2, dist1, dist2;
		start = intcrv->startParam(0);
		end = intcrv->endParam(0);
		intcrv->point(pt1, &start);
		intcrv->point(pt2, &end);
		surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		// Check curve
		coincident = checkCoincide(intcrv.get(), start, end,
					   intsf2.get(), Point(u1,v1), Point(u2,v2),
					   eps);
		if (!coincident)
		    return 0;
	    }
	}

	return 1;  // Coincidence
    }

}
<commit_msg>Fix for closed configurations<commit_after>//===========================================================================
//
// File: Identity.C
//
// Created:
//
// Author: Vibeke Skytt
//
// Revision:
//
// Description: Check for identical and embedded entities
//
//===========================================================================

#include "GoTools/intersections/Identity.h"
#include "GoTools/intersections/ParamSurfaceInt.h"
#include "GoTools/intersections/ParamCurveInt.h"
#include "GoTools/intersections/Coincidence.h"
#include "GoTools/intersections/GeoTol.h"

using std::vector;

namespace Go
{
    int Identity::identicalSfs(shared_ptr<ParamSurface> sf1,
			       shared_ptr<ParamSurface> sf2,
			       double tol)
    {
	// Initialize intersection objects
	shared_ptr<ParamSurfaceInt> intsf1 =
	    shared_ptr<ParamSurfaceInt>(new ParamSurfaceInt(sf1));
	shared_ptr<ParamSurfaceInt> intsf2 =
	    shared_ptr<ParamSurfaceInt>(new ParamSurfaceInt(sf2));
	shared_ptr<GeoTol> eps = shared_ptr<GeoTol>(new GeoTol(tol));

	// Fetch boundary elements
	vector<shared_ptr<BoundaryGeomInt> > bd_cvs1;
	vector<shared_ptr<BoundaryGeomInt> > bd_cvs2;

	intsf1->getBoundaryObjects(bd_cvs1);
	intsf2->getBoundaryObjects(bd_cvs2);

	// Check identity of boundary curves
	int ki, kj;
	int coincident = 0;
	double start1, start2, end1, end2;
	for (ki=0; ki<int(bd_cvs1.size()); ++ki)
	{
	    ParamCurveInt *cv1 = bd_cvs1[ki]->getObject()->getParamCurveInt();
	    start1 = cv1->startParam(0);
	    end1 = cv1->endParam(0);
	    for (kj=0; kj<int(bd_cvs2.size()); ++kj)
	    {
		ParamCurveInt *cv2 = bd_cvs2[kj]->getObject()->getParamCurveInt();
		start2 = cv2->startParam(0);
		end2 = cv2->endParam(0);

		// Check orientation
		Point pt1, pt2, pt3, pt4;
		cv1->point(pt1, &start1);
		cv1->point(pt2, &end1);
		cv2->point(pt3, &start2);
		cv2->point(pt4, &end2);
		if (!(pt1.dist(pt3) < tol || pt1.dist(pt4) < tol))
		    continue;
		if (!(pt2.dist(pt3) < tol || pt2.dist(pt4) < tol))
		    continue;
		if (pt1.dist(pt3) < pt1.dist(pt4))
		    coincident = checkCoincide(cv1, start1, end1, eps,
					       cv2, start2, end2);
		else
		    coincident = checkCoincide(cv1, start1, end1, eps,
					       cv2, end2, start2);
		if (coincident)
		    break;
	    }
	    if (kj == int(bd_cvs2.size()))
		break;  // No coincidence for this boundary curve
	}

	if (ki == int(bd_cvs1.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf1, intsf2, eps);
	    if (coincident)
		return 1;
	}

	// Check if the boundary curves of surface 1 lies in surface 2
	for (ki=0; ki<int(bd_cvs1.size()); ++ki)
	{
	    ParamCurveInt *cv1 = bd_cvs1[ki]->getObject()->getParamCurveInt();
	    start1 = cv1->startParam(0);
	    end1 = cv1->endParam(0);

	    // Project the endpoints onto surface 2
	    Point pt1, pt2, clo_pt1, clo_pt2;
	    double u1, v1, u2, v2, dist1, dist2;
	    cv1->point(pt1, &start1);
	    cv1->point(pt2, &end1);
	    sf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    sf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
	    if (dist2 > tol)
		break;  // No coincidence

	    // Check curve
	    coincident = checkCoincide(cv1, start1, end1,
				       intsf2.get(), Point(u1,v1), Point(u2,v2),
				       eps);
	    if (!coincident)
		break;
	}
	if (ki == int(bd_cvs1.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf1, intsf2, eps);
	    if (coincident)
		return 2;
	}

	// Check if the boundary curves of surface 2 lies in surface 1
	for (ki=0; ki<int(bd_cvs2.size()); ++ki)
	{
	    ParamCurveInt *cv2 = bd_cvs2[ki]->getObject()->getParamCurveInt();
	    start2 = cv2->startParam(0);
	    end2 = cv2->endParam(0);

	    // Project the endpoints onto surface 2
	    Point pt1, pt2, clo_pt1, clo_pt2;
	    double u1, v1, u2, v2, dist1, dist2;
	    cv2->point(pt1, &start2);
	    cv2->point(pt2, &end2);
	    sf1->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    sf1->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
	    if (dist1 > tol)
		break;  // No coincidence

	    // Check curve
	    coincident = checkCoincide(cv2, start2, end2,
				       intsf1.get(), Point(u1,v1), Point(u2,v2),
				       eps);
	    if (!coincident)
		break;
	}
	if (ki == int(bd_cvs2.size()))
	{
	    // Coincidence of boundary curves found. Check the inner
	    coincident = internalCoincidence(intsf2, intsf1, eps);
	    if (coincident)
		return 3;
	}

	// The surfaces are neither identical nor is one embedded in the other
	return 0;
    }

    int Identity::identicalCvs(shared_ptr<ParamCurve> cv1, double start1, double end1,
			       shared_ptr<ParamCurve> cv2, double start2, double end2,
			       double tol)
	// Check if two curves are identical, or one is embedded in the other.
	// The curve extension is limited by start and end parameters of each curve
    {
	// Box test
	BoundingBox box1 = cv1->boundingBox();
	BoundingBox box2 = cv2->boundingBox();
	if (!box1.overlaps(box2, tol))
	    return 0;

	// Initialize intersection objects
	shared_ptr<ParamCurveInt> intcv1 =
	    shared_ptr<ParamCurveInt>(new ParamCurveInt(cv1));
	shared_ptr<ParamCurveInt> intcv2 =
	    shared_ptr<ParamCurveInt>(new ParamCurveInt(cv2));
	shared_ptr<GeoTol> eps = shared_ptr<GeoTol>(new GeoTol(tol));

	// Check endpoints
	Point pt1, pt2, pt3, pt4;
	intcv1->point(pt1, &start1);
	intcv1->point(pt2, &end1);
	intcv2->point(pt3, &start2);
	intcv2->point(pt4, &end2);

	// First check coincidence
	int coincident = 0;
	if (pt1.dist(pt3) <= tol && pt2.dist(pt4) <= tol)
	    coincident = checkCoincide(intcv1.get(), start1, end1, eps,
				       intcv2.get(), start2, end2);
	else if (pt1.dist(pt4) <= tol && pt2.dist(pt3) <= tol)
	    coincident = checkCoincide(intcv1.get(), start1, end1, eps,
				       intcv2.get(), end2, start2);
	else
	{
	    // Project the endpoints on one curve onto the other curve and
	    // check for embedded curves
	    // First check if the first curve is embedded into the second
	    Point clo_pt1, clo_pt2;
	    double clo_dist1, clo_dist2;
	    double clo_par1, clo_par2;

	    cv2->closestPoint(pt1, start2, end2, clo_par1, clo_pt1, clo_dist1);
	    cv2->closestPoint(pt2, start2, end2, clo_par2, clo_pt2, clo_dist2);
	    if (clo_dist1 <= tol && clo_dist2 <= tol)
	    {
		// Posibility for embedded curve
		coincident = checkCoincide(intcv1.get(), start1, end1, eps,
					   intcv2.get(), clo_par1, clo_par2);
		if (coincident)
		    coincident = 2;
	    }

	    if (!coincident)
	    {
		// Check if curve two is embedded in curve one
		cv1->closestPoint(pt3, start1, end1, clo_par1, clo_pt1, clo_dist1);
		cv2->closestPoint(pt4, start1, end1, clo_par2, clo_pt2, clo_dist2);
		if (clo_dist1 <= tol && clo_dist2 <= tol)
		{
		    // Posibility for embedded curve
		    coincident = checkCoincide(intcv2.get(), start2, end2, eps,
					       intcv1.get(), clo_par1, clo_par2);
		    if (coincident)
			coincident = 3;
		}

	    }
	}

	return coincident;
    }

    int Identity::internalCoincidence(shared_ptr<ParamSurfaceInt>& intsf1,
				      shared_ptr<ParamSurfaceInt>& intsf2,
				      shared_ptr<GeoTol>& eps)
    {
	// Check if the first surface lies in the other.
	// The surface boundaries are already tested

	const RectDomain& domain = intsf1->getDomain();  // Surrounding parameter domain
	double umin = domain.umin();
	double umax = domain.umax();
	double vmin = domain.vmin();
	double vmax = domain.vmax();
	int nmb_sample_crvs = 10;
	double tint1 = (umax - umin)/(int)(nmb_sample_crvs+1);  // Only parameter values in the inner
	double tint2 = (vmax - vmin)/(int)(nmb_sample_crvs+1);

	// Check coincidence with surface 2 along a number of constant parameter curves of
	// surface 1 in both parameter directions
	// 1. parameter direction
	double par;
	int ki, kj;
	int coincident;
	shared_ptr<ParamSurface> surf1 = intsf1->getParamSurface();
	shared_ptr<ParamSurface> surf2 = intsf2->getParamSurface();
	double tol = eps->getEpsge();
	double rel_par_res = eps->getRelParRes();
	for (ki=0, par=umin+tint1; ki<nmb_sample_crvs; ++ki, par+=tint1)
	{
	    vector<shared_ptr<ParamCurve> > const_crvs = surf1->constParamCurves(par, false);
	    for (kj=0; kj<int(const_crvs.size()); ++kj)
	    {
		shared_ptr<ParamCurveInt> intcrv =
		    shared_ptr<ParamCurveInt>(new ParamCurveInt(const_crvs[kj]));

		// Project the endpoints onto surface 2
		double start, end;
		Point pt1, pt2, clo_pt1, clo_pt2;
		double u1, v1, u2, v2, dist1, dist2;
		start = intcrv->startParam(0);
		end = intcrv->endParam(0);
		intcrv->point(pt1, &start);
		intcrv->point(pt2, &end);
		surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		// Check curve
		Point parpt1(u1, v1);
		Point parpt2(u2, v2);
		coincident = checkCoincide(intcrv.get(), start, end,
					   intsf2.get(), parpt1, parpt2,
					   eps);
		if (!coincident)
		  {
		    // Extra check in closed configurations
		    if (pt1.dist(pt2) < tol && parpt1.dist(parpt2) < rel_par_res)
		      {
			double seed[2];
			Point pt3 = const_crvs[kj]->point(start + 0.1*(end-start));
			surf2->closestPoint(pt3, seed[0], seed[1], clo_pt1, dist1, tol);
			surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol, NULL, seed);

			Point pt4 = const_crvs[kj]->point(end - 0.1*(end-start));
			surf2->closestPoint(pt4, seed[0], seed[1], clo_pt2, dist2, tol);
			surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol, NULL, seed);
			if (dist1 > tol)
			  return 0;  // No coincidence

			// Check curve
			parpt1 = Point(u1, v1);
			parpt2 = Point(u2, v2);
			coincident = checkCoincide(intcrv.get(), start, end,
						   intsf2.get(), parpt1, parpt2,
						   eps);
			if (!coincident)
			  return 0;
		      }
		    else
		      return 0;
		  }
	    }
	}

	// 2. parameter direction
	for (ki=0, par=vmin+tint2; ki<nmb_sample_crvs; ++ki, par+=tint2)
	{
	    vector<shared_ptr<ParamCurve> > const_crvs = surf1->constParamCurves(par, true);
	    for (kj=0; kj<int(const_crvs.size()); ++kj)
	    {
		shared_ptr<ParamCurveInt> intcrv =
		    shared_ptr<ParamCurveInt>(new ParamCurveInt(const_crvs[kj]));

		// Project the endpoints onto surface 2
		double start, end;
		Point pt1, pt2, clo_pt1, clo_pt2;
		double u1, v1, u2, v2, dist1, dist2;
		start = intcrv->startParam(0);
		end = intcrv->endParam(0);
		intcrv->point(pt1, &start);
		intcrv->point(pt2, &end);
		surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol);
		if (dist1 > tol)
		    return 0;  // No coincidence

		// Check curve
		Point parpt1(u1, v1);
		Point parpt2(u2, v2);
		coincident = checkCoincide(intcrv.get(), start, end,
					   intsf2.get(), parpt1, parpt2,
					   eps);
		if (!coincident)
		  {
		    // Extra check in closed configurations
		    if (pt1.dist(pt2) < tol && parpt1.dist(parpt2) < rel_par_res)
		      {
			double seed[2];
			Point pt3 = const_crvs[kj]->point(start + 0.1*(end-start));
			surf2->closestPoint(pt3, seed[0], seed[1], clo_pt1, dist1, tol);
			surf2->closestPoint(pt1, u1, v1, clo_pt1, dist1, tol, NULL, seed);

			Point pt4 = const_crvs[kj]->point(end - 0.1*(end-start));
			surf2->closestPoint(pt4, seed[0], seed[1], clo_pt2, dist2, tol);
			surf2->closestPoint(pt2, u2, v2, clo_pt2, dist2, tol, NULL, seed);
			if (dist1 > tol)
			  return 0;  // No coincidence

			// Check curve
			parpt1 = Point(u1, v1);
			parpt2 = Point(u2, v2);
			coincident = checkCoincide(intcrv.get(), start, end,
						   intsf2.get(), parpt1, parpt2,
						   eps);
			if (!coincident)
			  return 0;
		      }
		    else
		    return 0;
		  }
	    }
	}

	return 1;  // Coincidence
    }

}
<|endoftext|>


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

#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/task_management/task_management_browsertest_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/printing/common/print_messages.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test_utils.h"
#include "ipc/ipc_message_macros.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using content::WebContents;
using content::WebContentsObserver;

namespace {

class RequestPrintPreviewObserver : public WebContentsObserver {
 public:
  explicit RequestPrintPreviewObserver(WebContents* dialog)
      : WebContentsObserver(dialog) {
  }
  ~RequestPrintPreviewObserver() override {}

  void set_quit_closure(const base::Closure& quit_closure) {
    quit_closure_ = quit_closure;
  }

 private:
  // content::WebContentsObserver implementation.
  bool OnMessageReceived(const IPC::Message& message) override {
    IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
      IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
                          OnRequestPrintPreview)
      IPC_MESSAGE_UNHANDLED(break;)
    IPC_END_MESSAGE_MAP();
    return false;  // Report not handled so the real handler receives it.
  }

  void OnRequestPrintPreview(
      const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
  }

  base::Closure quit_closure_;

  DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
};

class PrintPreviewDialogClonedObserver : public WebContentsObserver {
 public:
  explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
      : WebContentsObserver(dialog) {
  }
  ~PrintPreviewDialogClonedObserver() override {}

  RequestPrintPreviewObserver* request_preview_dialog_observer() {
    return request_preview_dialog_observer_.get();
  }

 private:
  // content::WebContentsObserver implementation.
  void DidCloneToNewWebContents(WebContents* old_web_contents,
                                WebContents* new_web_contents) override {
    request_preview_dialog_observer_.reset(
        new RequestPrintPreviewObserver(new_web_contents));
  }

  scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
};

class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
 public:
  explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
      : WebContentsObserver(dialog),
        dialog_destroyed_(false) {
  }
  ~PrintPreviewDialogDestroyedObserver() override {}

  bool dialog_destroyed() const { return dialog_destroyed_; }

 private:
  // content::WebContentsObserver implementation.
  void WebContentsDestroyed() override { dialog_destroyed_ = true; }

  bool dialog_destroyed_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
};

void PluginsLoadedCallback(
    const base::Closure& quit_closure,
    const std::vector<content::WebPluginInfo>& /* info */) {
  quit_closure.Run();
}

bool GetPdfPluginInfo(content::WebPluginInfo* info) {
  base::FilePath pdf_plugin_path = base::FilePath::FromUTF8Unsafe(
      ChromeContentClient::kPDFPluginPath);
  return content::PluginService::GetInstance()->GetPluginInfoByPath(
      pdf_plugin_path, info);
}

const char kDummyPrintUrl[] = "chrome://print/dummy.pdf";

void CountFrames(int* frame_count,
                 content::RenderFrameHost* frame) {
  ++(*frame_count);
}

void CheckPdfPluginForRenderFrame(content::RenderFrameHost* frame) {
  content::WebPluginInfo pdf_plugin_info;
  ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));

  ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
  EXPECT_TRUE(filter->IsPluginAvailable(
      frame->GetProcess()->GetID(),
      frame->GetRoutingID(),
      nullptr,
      GURL(kDummyPrintUrl),
      GURL(),
      &pdf_plugin_info));
}

}  // namespace

class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
 public:
  PrintPreviewDialogControllerBrowserTest() : initiator_(nullptr) {}
  ~PrintPreviewDialogControllerBrowserTest() override {}

  WebContents* initiator() {
    return initiator_;
  }

  void PrintPreview() {
    base::RunLoop run_loop;
    request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
    chrome::Print(browser());
    run_loop.Run();
  }

  WebContents* GetPrintPreviewDialog() {
    printing::PrintPreviewDialogController* dialog_controller =
        printing::PrintPreviewDialogController::GetInstance();
    return dialog_controller->GetPrintPreviewForContents(initiator_);
  }

 private:
  void SetUpOnMainThread() override {
    WebContents* first_tab =
        browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(first_tab);

    // Open a new tab so |cloned_tab_observer_| can see it first and attach a
    // RequestPrintPreviewObserver to it before the real
    // PrintPreviewMessageHandler gets created. Thus enabling
    // RequestPrintPreviewObserver to get messages first for the purposes of
    // this test.
    cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
    chrome::DuplicateTab(browser());

    initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(initiator_);
    ASSERT_NE(first_tab, initiator_);

    content::PluginService::GetInstance()->Init();
    content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
  }

  void TearDownOnMainThread() override {
    cloned_tab_observer_.reset();
    initiator_ = nullptr;
  }

  RequestPrintPreviewObserver* request_preview_dialog_observer() {
    return cloned_tab_observer_->request_preview_dialog_observer();
  }

  scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
  WebContents* initiator_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
};

// Test to verify that when a initiator navigates, we can create a new preview
// dialog for the new tab contents.
// http://crbug.com/377337
#if defined(OS_WIN)
#define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
#else
#define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
#endif
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       MAYBE_NavigateFromInitiatorTab) {
  // Print for the first time.
  PrintPreview();

  // Get the preview dialog for the initiator tab.
  WebContents* preview_dialog = GetPrintPreviewDialog();

  // Check a new print preview dialog got created.
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Navigate in the initiator tab. Make sure navigating destroys the print
  // preview dialog.
  PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
  ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());

  // Try printing again.
  PrintPreview();

  // Get the print preview dialog for the initiator tab.
  WebContents* new_preview_dialog = GetPrintPreviewDialog();

  // Check a new preview dialog got created.
  EXPECT_TRUE(new_preview_dialog);
}

// Test to verify that after reloading the initiator, it creates a new print
// preview dialog.
// http://crbug.com/377337
#if defined(OS_WIN)
#define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
#else
#define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
#endif
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       MAYBE_ReloadInitiatorTab) {
  // Print for the first time.
  PrintPreview();

  WebContents* preview_dialog = GetPrintPreviewDialog();

  // Check a new print preview dialog got created.
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Reload the initiator. Make sure reloading destroys the print preview
  // dialog.
  PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
  chrome::Reload(browser(), CURRENT_TAB);
  content::WaitForLoadStop(
      browser()->tab_strip_model()->GetActiveWebContents());
  ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());

  // Try printing again.
  PrintPreview();

  // Create a preview dialog for the initiator tab.
  WebContents* new_preview_dialog = GetPrintPreviewDialog();
  EXPECT_TRUE(new_preview_dialog);
}

// Test to verify that after print preview works even when the PDF plugin is
// disabled for webpages.
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       PdfPluginDisabled) {
  // Make sure plugins are loaded.
  {
    base::RunLoop run_loop;
    content::PluginService::GetInstance()->GetPlugins(
        base::Bind(&PluginsLoadedCallback, run_loop.QuitClosure()));
    run_loop.Run();
  }
  // Get the PDF plugin info.
  content::WebPluginInfo pdf_plugin_info;
  ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));

  // Disable the PDF plugin.
  PluginPrefs::GetForProfile(browser()->profile())->EnablePluginGroup(
      false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName));

  // Make sure it is actually disabled for webpages.
  ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
  content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
  EXPECT_FALSE(filter->IsPluginAvailable(
      initiator()->GetRenderProcessHost()->GetID(),
      initiator()->GetMainFrame()->GetRoutingID(),
      nullptr,
      GURL("http://google.com"),
      GURL(),
      &dummy_pdf_plugin_info));

  PrintPreview();

  // Check a new print preview dialog got created.
  WebContents* preview_dialog = GetPrintPreviewDialog();
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Wait until the <iframe> in the print preview renderer has loaded.
  // |frame_count| should be 2. The other frame is the main frame.
  const int kExpectedFrameCount = 2;
  int frame_count;
  do {
    base::RunLoop run_loop;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
    run_loop.Run();

    frame_count = 0;
    preview_dialog->ForEachFrame(
        base::Bind(&CountFrames, base::Unretained(&frame_count)));
  } while (frame_count < kExpectedFrameCount);
  ASSERT_EQ(kExpectedFrameCount, frame_count);

  // Make sure all the frames in the dialog has access to the PDF plugin.
  preview_dialog->ForEachFrame(base::Bind(&CheckPdfPluginForRenderFrame));
}

#if defined(ENABLE_TASK_MANAGER)

namespace {

base::string16 GetExpectedPrefix() {
  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
                                    base::string16());
}

const std::vector<task_management::WebContentsTag*>& GetTrackedTags() {
  return task_management::WebContentsTagsManager::GetInstance()->
      tracked_tags();
}

IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       TaskManagementTest) {
  // This test starts with two tabs open.
  EXPECT_EQ(2U, GetTrackedTags().size());

  PrintPreview();
  EXPECT_EQ(3U, GetTrackedTags().size());

  // Create a task manager and expect the pre-existing print previews are
  // provided.
  task_management::MockWebContentsTaskManager task_manager;
  EXPECT_TRUE(task_manager.tasks().empty());
  task_manager.StartObserving();
  EXPECT_EQ(3U, task_manager.tasks().size());
  const task_management::Task* pre_existing_task = task_manager.tasks().back();
  EXPECT_EQ(task_management::Task::RENDERER, pre_existing_task->GetType());
  const base::string16 pre_existing_title = pre_existing_task->title();
  const base::string16 expected_prefix = GetExpectedPrefix();
  EXPECT_TRUE(base::StartsWith(pre_existing_title,
                               expected_prefix,
                               base::CompareCase::INSENSITIVE_ASCII));

  // Navigating away from the current page in the current tab for which a print
  // preview is displayed will cancel the print preview and hence the task
  // manger shouldn't show a printing task.
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
  EXPECT_EQ(2U, GetTrackedTags().size());
  EXPECT_EQ(2U, task_manager.tasks().size());

  // Now start another print preview after the had already been created and
  // validated that a corresponding task is reported.
  PrintPreview();
  EXPECT_EQ(3U, GetTrackedTags().size());
  EXPECT_EQ(3U, task_manager.tasks().size());
  const task_management::Task* task = task_manager.tasks().back();
  EXPECT_EQ(task_management::Task::RENDERER, task->GetType());
  const base::string16 title = task->title();
  EXPECT_TRUE(base::StartsWith(title,
                               expected_prefix,
                               base::CompareCase::INSENSITIVE_ASCII));
}

}  // namespace

#endif  // defined(ENABLE_TASK_MANAGER)
<commit_msg>Make The task manager browser tests for the print preview work under --site-per-process<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/task_management/task_management_browsertest_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/printing/common/print_messages.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/browser_test_utils.h"
#include "ipc/ipc_message_macros.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using content::WebContents;
using content::WebContentsObserver;

namespace {

class RequestPrintPreviewObserver : public WebContentsObserver {
 public:
  explicit RequestPrintPreviewObserver(WebContents* dialog)
      : WebContentsObserver(dialog) {
  }
  ~RequestPrintPreviewObserver() override {}

  void set_quit_closure(const base::Closure& quit_closure) {
    quit_closure_ = quit_closure;
  }

 private:
  // content::WebContentsObserver implementation.
  bool OnMessageReceived(const IPC::Message& message) override {
    IPC_BEGIN_MESSAGE_MAP(RequestPrintPreviewObserver, message)
      IPC_MESSAGE_HANDLER(PrintHostMsg_RequestPrintPreview,
                          OnRequestPrintPreview)
      IPC_MESSAGE_UNHANDLED(break;)
    IPC_END_MESSAGE_MAP();
    return false;  // Report not handled so the real handler receives it.
  }

  void OnRequestPrintPreview(
      const PrintHostMsg_RequestPrintPreview_Params& /* params */) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, quit_closure_);
  }

  base::Closure quit_closure_;

  DISALLOW_COPY_AND_ASSIGN(RequestPrintPreviewObserver);
};

class PrintPreviewDialogClonedObserver : public WebContentsObserver {
 public:
  explicit PrintPreviewDialogClonedObserver(WebContents* dialog)
      : WebContentsObserver(dialog) {
  }
  ~PrintPreviewDialogClonedObserver() override {}

  RequestPrintPreviewObserver* request_preview_dialog_observer() {
    return request_preview_dialog_observer_.get();
  }

 private:
  // content::WebContentsObserver implementation.
  void DidCloneToNewWebContents(WebContents* old_web_contents,
                                WebContents* new_web_contents) override {
    request_preview_dialog_observer_.reset(
        new RequestPrintPreviewObserver(new_web_contents));
  }

  scoped_ptr<RequestPrintPreviewObserver> request_preview_dialog_observer_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogClonedObserver);
};

class PrintPreviewDialogDestroyedObserver : public WebContentsObserver {
 public:
  explicit PrintPreviewDialogDestroyedObserver(WebContents* dialog)
      : WebContentsObserver(dialog),
        dialog_destroyed_(false) {
  }
  ~PrintPreviewDialogDestroyedObserver() override {}

  bool dialog_destroyed() const { return dialog_destroyed_; }

 private:
  // content::WebContentsObserver implementation.
  void WebContentsDestroyed() override { dialog_destroyed_ = true; }

  bool dialog_destroyed_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogDestroyedObserver);
};

void PluginsLoadedCallback(
    const base::Closure& quit_closure,
    const std::vector<content::WebPluginInfo>& /* info */) {
  quit_closure.Run();
}

bool GetPdfPluginInfo(content::WebPluginInfo* info) {
  base::FilePath pdf_plugin_path = base::FilePath::FromUTF8Unsafe(
      ChromeContentClient::kPDFPluginPath);
  return content::PluginService::GetInstance()->GetPluginInfoByPath(
      pdf_plugin_path, info);
}

const char kDummyPrintUrl[] = "chrome://print/dummy.pdf";

void CountFrames(int* frame_count,
                 content::RenderFrameHost* frame) {
  ++(*frame_count);
}

void CheckPdfPluginForRenderFrame(content::RenderFrameHost* frame) {
  content::WebPluginInfo pdf_plugin_info;
  ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));

  ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
  EXPECT_TRUE(filter->IsPluginAvailable(
      frame->GetProcess()->GetID(),
      frame->GetRoutingID(),
      nullptr,
      GURL(kDummyPrintUrl),
      GURL(),
      &pdf_plugin_info));
}

}  // namespace

class PrintPreviewDialogControllerBrowserTest : public InProcessBrowserTest {
 public:
  PrintPreviewDialogControllerBrowserTest() : initiator_(nullptr) {}
  ~PrintPreviewDialogControllerBrowserTest() override {}

  WebContents* initiator() {
    return initiator_;
  }

  void PrintPreview() {
    base::RunLoop run_loop;
    request_preview_dialog_observer()->set_quit_closure(run_loop.QuitClosure());
    chrome::Print(browser());
    run_loop.Run();
  }

  WebContents* GetPrintPreviewDialog() {
    printing::PrintPreviewDialogController* dialog_controller =
        printing::PrintPreviewDialogController::GetInstance();
    return dialog_controller->GetPrintPreviewForContents(initiator_);
  }

 private:
  void SetUpOnMainThread() override {
    WebContents* first_tab =
        browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(first_tab);

    // Open a new tab so |cloned_tab_observer_| can see it first and attach a
    // RequestPrintPreviewObserver to it before the real
    // PrintPreviewMessageHandler gets created. Thus enabling
    // RequestPrintPreviewObserver to get messages first for the purposes of
    // this test.
    cloned_tab_observer_.reset(new PrintPreviewDialogClonedObserver(first_tab));
    chrome::DuplicateTab(browser());

    initiator_ = browser()->tab_strip_model()->GetActiveWebContents();
    ASSERT_TRUE(initiator_);
    ASSERT_NE(first_tab, initiator_);

    content::PluginService::GetInstance()->Init();
    content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
  }

  void TearDownOnMainThread() override {
    cloned_tab_observer_.reset();
    initiator_ = nullptr;
  }

  RequestPrintPreviewObserver* request_preview_dialog_observer() {
    return cloned_tab_observer_->request_preview_dialog_observer();
  }

  scoped_ptr<PrintPreviewDialogClonedObserver> cloned_tab_observer_;
  WebContents* initiator_;

  DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogControllerBrowserTest);
};

// Test to verify that when a initiator navigates, we can create a new preview
// dialog for the new tab contents.
// http://crbug.com/377337
#if defined(OS_WIN)
#define MAYBE_NavigateFromInitiatorTab DISABLED_NavigateFromInitiatorTab
#else
#define MAYBE_NavigateFromInitiatorTab NavigateFromInitiatorTab
#endif
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       MAYBE_NavigateFromInitiatorTab) {
  // Print for the first time.
  PrintPreview();

  // Get the preview dialog for the initiator tab.
  WebContents* preview_dialog = GetPrintPreviewDialog();

  // Check a new print preview dialog got created.
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Navigate in the initiator tab. Make sure navigating destroys the print
  // preview dialog.
  PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
  ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());

  // Try printing again.
  PrintPreview();

  // Get the print preview dialog for the initiator tab.
  WebContents* new_preview_dialog = GetPrintPreviewDialog();

  // Check a new preview dialog got created.
  EXPECT_TRUE(new_preview_dialog);
}

// Test to verify that after reloading the initiator, it creates a new print
// preview dialog.
// http://crbug.com/377337
#if defined(OS_WIN)
#define MAYBE_ReloadInitiatorTab DISABLED_ReloadInitiatorTab
#else
#define MAYBE_ReloadInitiatorTab ReloadInitiatorTab
#endif
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       MAYBE_ReloadInitiatorTab) {
  // Print for the first time.
  PrintPreview();

  WebContents* preview_dialog = GetPrintPreviewDialog();

  // Check a new print preview dialog got created.
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Reload the initiator. Make sure reloading destroys the print preview
  // dialog.
  PrintPreviewDialogDestroyedObserver dialog_destroyed_observer(preview_dialog);
  chrome::Reload(browser(), CURRENT_TAB);
  content::WaitForLoadStop(
      browser()->tab_strip_model()->GetActiveWebContents());
  ASSERT_TRUE(dialog_destroyed_observer.dialog_destroyed());

  // Try printing again.
  PrintPreview();

  // Create a preview dialog for the initiator tab.
  WebContents* new_preview_dialog = GetPrintPreviewDialog();
  EXPECT_TRUE(new_preview_dialog);
}

// Test to verify that after print preview works even when the PDF plugin is
// disabled for webpages.
IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       PdfPluginDisabled) {
  // Make sure plugins are loaded.
  {
    base::RunLoop run_loop;
    content::PluginService::GetInstance()->GetPlugins(
        base::Bind(&PluginsLoadedCallback, run_loop.QuitClosure()));
    run_loop.Run();
  }
  // Get the PDF plugin info.
  content::WebPluginInfo pdf_plugin_info;
  ASSERT_TRUE(GetPdfPluginInfo(&pdf_plugin_info));

  // Disable the PDF plugin.
  PluginPrefs::GetForProfile(browser()->profile())->EnablePluginGroup(
      false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName));

  // Make sure it is actually disabled for webpages.
  ChromePluginServiceFilter* filter = ChromePluginServiceFilter::GetInstance();
  content::WebPluginInfo dummy_pdf_plugin_info = pdf_plugin_info;
  EXPECT_FALSE(filter->IsPluginAvailable(
      initiator()->GetRenderProcessHost()->GetID(),
      initiator()->GetMainFrame()->GetRoutingID(),
      nullptr,
      GURL("http://google.com"),
      GURL(),
      &dummy_pdf_plugin_info));

  PrintPreview();

  // Check a new print preview dialog got created.
  WebContents* preview_dialog = GetPrintPreviewDialog();
  ASSERT_TRUE(preview_dialog);
  ASSERT_NE(initiator(), preview_dialog);

  // Wait until the <iframe> in the print preview renderer has loaded.
  // |frame_count| should be 2. The other frame is the main frame.
  const int kExpectedFrameCount = 2;
  int frame_count;
  do {
    base::RunLoop run_loop;
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
    run_loop.Run();

    frame_count = 0;
    preview_dialog->ForEachFrame(
        base::Bind(&CountFrames, base::Unretained(&frame_count)));
  } while (frame_count < kExpectedFrameCount);
  ASSERT_EQ(kExpectedFrameCount, frame_count);

  // Make sure all the frames in the dialog has access to the PDF plugin.
  preview_dialog->ForEachFrame(base::Bind(&CheckPdfPluginForRenderFrame));
}

#if defined(ENABLE_TASK_MANAGER)

namespace {

base::string16 GetExpectedPrefix() {
  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
                                    base::string16());
}

const std::vector<task_management::WebContentsTag*>& GetTrackedTags() {
  return task_management::WebContentsTagsManager::GetInstance()->
      tracked_tags();
}

IN_PROC_BROWSER_TEST_F(PrintPreviewDialogControllerBrowserTest,
                       TaskManagementTest) {
  // This test starts with two tabs open.
  EXPECT_EQ(2U, GetTrackedTags().size());

  PrintPreview();
  EXPECT_EQ(3U, GetTrackedTags().size());

  // Create a task manager and expect the pre-existing print previews are
  // provided.
  task_management::MockWebContentsTaskManager task_manager;
  EXPECT_TRUE(task_manager.tasks().empty());
  task_manager.StartObserving();
  EXPECT_EQ(3U, task_manager.tasks().size());
  const task_management::Task* pre_existing_task = task_manager.tasks().back();
  EXPECT_EQ(task_management::Task::RENDERER, pre_existing_task->GetType());
  const base::string16 pre_existing_title = pre_existing_task->title();
  const base::string16 expected_prefix = GetExpectedPrefix();
  EXPECT_TRUE(base::StartsWith(pre_existing_title,
                               expected_prefix,
                               base::CompareCase::INSENSITIVE_ASCII));

  // Navigating away from the current page in the current tab for which a print
  // preview is displayed will cancel the print preview and hence the task
  // manger shouldn't show a printing task.
  ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
  EXPECT_EQ(2U, GetTrackedTags().size());
  EXPECT_EQ(2U, task_manager.tasks().size());

  // Now start another print preview after the had already been created and
  // validated that a corresponding task is reported.
  PrintPreview();
  EXPECT_EQ(3U, GetTrackedTags().size());
  EXPECT_EQ(3U, task_manager.tasks().size());
  const task_management::Task* task = task_manager.tasks().back();
  EXPECT_EQ(task_management::Task::RENDERER, task->GetType());
  const base::string16 title = task->title();
  EXPECT_TRUE(base::StartsWith(title,
                               expected_prefix,
                               base::CompareCase::INSENSITIVE_ASCII));
}

}  // namespace

#endif  // defined(ENABLE_TASK_MANAGER)
<|endoftext|>


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

#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/test/net/url_request_mock_http_job.h"
#include "testing/gtest/include/gtest/gtest.h"

class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest {
 public:
  BrowsingDataRemoverBrowserTest() {}

  void RunScriptAndCheckResult(const std::wstring& script,
                               const std::string& result) {
    std::string data;
    ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
        chrome::GetActiveWebContents(browser())->GetRenderViewHost(), L"",
        script, &data));
    ASSERT_EQ(data, result);
  }

  void RemoveAndWait(int remove_mask) {
    content::WindowedNotificationObserver signal(
        chrome::NOTIFICATION_BROWSING_DATA_REMOVED,
        content::Source<Profile>(browser()->profile()));
    BrowsingDataRemover* remover = new BrowsingDataRemover(
        browser()->profile(), BrowsingDataRemover::LAST_HOUR,
        base::Time::Now() + base::TimeDelta::FromMilliseconds(10));
    remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
    signal.Wait();
  }
};

// Test BrowsingDataRemover for downloads.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Download) {
  // Start a download.
  content::DownloadManager* download_manager =
      content::BrowserContext::GetDownloadManager(browser()->profile());
  scoped_ptr<content::DownloadTestObserver> observer(
      new content::DownloadTestObserverTerminal(
          download_manager, 1,
          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));

  GURL download_url = ui_test_utils::GetTestUrl(
      FilePath().AppendASCII("downloads"),
      FilePath().AppendASCII("a_zip_file.zip"));
  ui_test_utils::NavigateToURL(browser(), download_url);
  observer->WaitForFinished();

  std::vector<content::DownloadItem*> downloads;
  download_manager->GetAllDownloads(FilePath(), &downloads);
  EXPECT_EQ(1u, downloads.size());

  RemoveAndWait(BrowsingDataRemover::REMOVE_DOWNLOADS);

  downloads.clear();
  download_manager->GetAllDownloads(FilePath(), &downloads);
  EXPECT_TRUE(downloads.empty());
}
#if !defined(OS_LINUX)
// Verify can modify database after deleting it.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Database) {
  ASSERT_TRUE(test_server()->Start());
  GURL url = test_server()->GetURL("files/database/simple_database.html");
  ui_test_utils::NavigateToURL(browser(), url);

  RunScriptAndCheckResult(L"createTable()", "done");
  RunScriptAndCheckResult(L"insertRecord('text')", "done");
  RunScriptAndCheckResult(L"getRecords()", "text");

  RemoveAndWait(BrowsingDataRemover::REMOVE_SITE_DATA);

  ui_test_utils::NavigateToURL(browser(), url);
  RunScriptAndCheckResult(L"createTable()", "done");
  RunScriptAndCheckResult(L"insertRecord('text2')", "done");
  RunScriptAndCheckResult(L"getRecords()", "text2");
}
#endif
<commit_msg>Disable the right test<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/test/net/url_request_mock_http_job.h"
#include "testing/gtest/include/gtest/gtest.h"

class BrowsingDataRemoverBrowserTest : public InProcessBrowserTest {
 public:
  BrowsingDataRemoverBrowserTest() {}

  void RunScriptAndCheckResult(const std::wstring& script,
                               const std::string& result) {
    std::string data;
    ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
        chrome::GetActiveWebContents(browser())->GetRenderViewHost(), L"",
        script, &data));
    ASSERT_EQ(data, result);
  }

  void RemoveAndWait(int remove_mask) {
    content::WindowedNotificationObserver signal(
        chrome::NOTIFICATION_BROWSING_DATA_REMOVED,
        content::Source<Profile>(browser()->profile()));
    BrowsingDataRemover* remover = new BrowsingDataRemover(
        browser()->profile(), BrowsingDataRemover::LAST_HOUR,
        base::Time::Now() + base::TimeDelta::FromMilliseconds(10));
    remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
    signal.Wait();
  }
};
#if !defined(OS_LINUX)
// Test BrowsingDataRemover for downloads.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Download) {
  // Start a download.
  content::DownloadManager* download_manager =
      content::BrowserContext::GetDownloadManager(browser()->profile());
  scoped_ptr<content::DownloadTestObserver> observer(
      new content::DownloadTestObserverTerminal(
          download_manager, 1,
          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT));

  GURL download_url = ui_test_utils::GetTestUrl(
      FilePath().AppendASCII("downloads"),
      FilePath().AppendASCII("a_zip_file.zip"));
  ui_test_utils::NavigateToURL(browser(), download_url);
  observer->WaitForFinished();

  std::vector<content::DownloadItem*> downloads;
  download_manager->GetAllDownloads(FilePath(), &downloads);
  EXPECT_EQ(1u, downloads.size());

  RemoveAndWait(BrowsingDataRemover::REMOVE_DOWNLOADS);

  downloads.clear();
  download_manager->GetAllDownloads(FilePath(), &downloads);
  EXPECT_TRUE(downloads.empty());
}
#endif
// Verify can modify database after deleting it.
IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, Database) {
  ASSERT_TRUE(test_server()->Start());
  GURL url = test_server()->GetURL("files/database/simple_database.html");
  ui_test_utils::NavigateToURL(browser(), url);

  RunScriptAndCheckResult(L"createTable()", "done");
  RunScriptAndCheckResult(L"insertRecord('text')", "done");
  RunScriptAndCheckResult(L"getRecords()", "text");

  RemoveAndWait(BrowsingDataRemover::REMOVE_SITE_DATA);

  ui_test_utils::NavigateToURL(browser(), url);
  RunScriptAndCheckResult(L"createTable()", "done");
  RunScriptAndCheckResult(L"insertRecord('text2')", "done");
  RunScriptAndCheckResult(L"getRecords()", "text2");
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");
    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

TEST_F(GtkKeyBindingsHandlerTest, MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

TEST_F(GtkKeyBindingsHandlerTest, OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<commit_msg>Mark the GtkKeyBindingsHandlerTest  tests as flaky since they don't work in a chroot.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/renderer_host/gtk_key_bindings_handler.h"

#include <gdk/gdkkeysyms.h>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/edit_command.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "testing/gtest/include/gtest/gtest.h"

class GtkKeyBindingsHandlerTest : public testing::Test {
 protected:
  struct EditCommand {
    const char* name;
    const char* value;
  };

  GtkKeyBindingsHandlerTest()
      : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
        handler_(NULL) {
    FilePath gtkrc;
    PathService::Get(chrome::DIR_TEST_DATA, &gtkrc);
    gtkrc = gtkrc.AppendASCII("gtk_key_bindings_test_gtkrc");
    gtk_rc_parse(gtkrc.value().c_str());

    GtkWidget* fixed = gtk_fixed_new();
    handler_ = new GtkKeyBindingsHandler(fixed);
    gtk_container_add(GTK_CONTAINER(window_), fixed);
    gtk_widget_show(fixed);
    gtk_widget_show(window_);
  }
  ~GtkKeyBindingsHandlerTest() {
    gtk_widget_destroy(window_);
    delete handler_;
  }

  NativeWebKeyboardEvent NewNativeWebKeyboardEvent(guint keyval, guint state) {
    GdkKeymap* keymap =
        gdk_keymap_get_for_display(gtk_widget_get_display(window_));

    GdkKeymapKey *keys = NULL;
    gint n_keys = 0;
    if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
      GdkEventKey event;
      event.type = GDK_KEY_PRESS;
      event.window = NULL;
      event.send_event = 0;
      event.time = 0;
      event.state = state;
      event.keyval = keyval;
      event.length = 0;
      event.string = NULL;
      event.hardware_keycode = keys[0].keycode;
      event.group = keys[0].group;
      event.is_modifier = 0;
      g_free(keys);
      return NativeWebKeyboardEvent(&event);
    }
    return NativeWebKeyboardEvent();
  }

  void TestKeyBinding(const NativeWebKeyboardEvent& event,
                      const EditCommand expected_result[],
                      size_t size) {
    EditCommands result;
    ASSERT_TRUE(handler_->Match(event, &result));
    ASSERT_EQ(size, result.size());
    for (size_t i = 0; i < size; ++i) {
      ASSERT_STREQ(expected_result[i].name, result[i].name.c_str());
      ASSERT_STREQ(expected_result[i].value, result[i].value.c_str());
    }
  }

 protected:
  GtkWidget* window_;
  GtkKeyBindingsHandler* handler_;
};

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_MoveCursor) {
  static const EditCommand kEditCommands[] = {
    // "move-cursor" (logical-positions, -2, 0)
    { "MoveBackward", "" },
    { "MoveBackward", "" },
    // "move-cursor" (logical-positions, 2, 0)
    { "MoveForward", "" },
    { "MoveForward", "" },
    // "move-cursor" (visual-positions, -1, 1)
    { "MoveLeftAndModifySelection", "" },
    // "move-cursor" (visual-positions, 1, 1)
    { "MoveRightAndModifySelection", "" },
    // "move-cursor" (words, -1, 0)
    { "MoveWordBackward", "" },
    // "move-cursor" (words, 1, 0)
    { "MoveWordForward", "" },
    // "move-cursor" (display-lines, -1, 0)
    { "MoveUp", "" },
    // "move-cursor" (display-lines, 1, 0)
    { "MoveDown", "" },
    // "move-cursor" (display-line-ends, -1, 0)
    { "MoveToBeginningOfLine", "" },
    // "move-cursor" (display-line-ends, 1, 0)
    { "MoveToEndOfLine", "" },
    // "move-cursor" (paragraph-ends, -1, 0)
    { "MoveToBeginningOfParagraph", "" },
    // "move-cursor" (paragraph-ends, 1, 0)
    { "MoveToEndOfParagraph", "" },
    // "move-cursor" (pages, -1, 0)
    { "MovePageUp", "" },
    // "move-cursor" (pages, 1, 0)
    { "MovePageDown", "" },
    // "move-cursor" (buffer-ends, -1, 0)
    { "MoveToBeginningOfDocument", "" },
    // "move-cursor" (buffer-ends, 1, 0)
    { "MoveToEndOfDocument", "" }
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_1, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_DeleteFromCursor) {
  static const EditCommand kEditCommands[] = {
    // "delete-from-cursor" (chars, -2)
    { "DeleteBackward", "" },
    { "DeleteBackward", "" },
    // "delete-from-cursor" (chars, 2)
    { "DeleteForward", "" },
    { "DeleteForward", "" },
    // "delete-from-cursor" (word-ends, -1)
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (word-ends, 1)
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, -1)
    { "MoveWordBackward", "" },
    { "DeleteWordForward", "" },
    // "delete-from-cursor" (words, 1)
    { "MoveWordForward", "" },
    { "DeleteWordBackward", "" },
    // "delete-from-cursor" (display-lines, -1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-lines, 1)
    { "MoveToBeginningOfLine", "" },
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (display-line-ends, -1)
    { "DeleteToBeginningOfLine", "" },
    // "delete-from-cursor" (display-line-ends, 1)
    { "DeleteToEndOfLine", "" },
    // "delete-from-cursor" (paragraph-ends, -1)
    { "DeleteToBeginningOfParagraph", "" },
    // "delete-from-cursor" (paragraph-ends, 1)
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, -1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
    // "delete-from-cursor" (paragraphs, 1)
    { "MoveToBeginningOfParagraph", "" },
    { "DeleteToEndOfParagraph", "" },
  };

  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_2, GDK_CONTROL_MASK),
                 kEditCommands, arraysize(kEditCommands));
}

// Does not work in a chroot. See bug 60363.
TEST_F(GtkKeyBindingsHandlerTest, FLAKY_OtherActions) {
  static const EditCommand kBackspace[] = {
    { "DeleteBackward", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_3, GDK_CONTROL_MASK),
                 kBackspace, arraysize(kBackspace));

  static const EditCommand kCopyClipboard[] = {
    { "Copy", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_4, GDK_CONTROL_MASK),
                 kCopyClipboard, arraysize(kCopyClipboard));

  static const EditCommand kCutClipboard[] = {
    { "Cut", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_5, GDK_CONTROL_MASK),
                 kCutClipboard, arraysize(kCutClipboard));

  static const EditCommand kInsertAtCursor[] = {
    { "InsertText", "hello" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_6, GDK_CONTROL_MASK),
                 kInsertAtCursor, arraysize(kInsertAtCursor));

  static const EditCommand kPasteClipboard[] = {
    { "Paste", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_7, GDK_CONTROL_MASK),
                 kPasteClipboard, arraysize(kPasteClipboard));

  static const EditCommand kSelectAll[] = {
    { "Unselect", "" },
    { "SelectAll", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_8, GDK_CONTROL_MASK),
                 kSelectAll, arraysize(kSelectAll));

  static const EditCommand kSetAnchor[] = {
    { "SetMark", "" }
  };
  TestKeyBinding(NewNativeWebKeyboardEvent(GDK_9, GDK_CONTROL_MASK),
                 kSetAnchor, arraysize(kSetAnchor));
}
<|endoftext|>


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

// minidump_dump.cc: Print the contents of a minidump file in somewhat
// readable text.
//
// Author: Mark Mentovai

#include <stdio.h>

#include "google_breakpad/processor/minidump.h"
#include "processor/logging.h"

namespace {

using google_breakpad::Minidump;
using google_breakpad::MinidumpThreadList;
using google_breakpad::MinidumpModuleList;
using google_breakpad::MinidumpMemoryList;
using google_breakpad::MinidumpException;
using google_breakpad::MinidumpAssertion;
using google_breakpad::MinidumpSystemInfo;
using google_breakpad::MinidumpMiscInfo;
using google_breakpad::MinidumpBreakpadInfo;

static bool PrintMinidumpDump(const char *minidump_file) {
  Minidump minidump(minidump_file);
  if (!minidump.Read()) {
    BPLOG(ERROR) << "minidump.Read() failed";
    return false;
  }
  minidump.Print();

  int errors = 0;

  MinidumpThreadList *thread_list = minidump.GetThreadList();
  if (!thread_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetThreadList() failed";
  } else {
    thread_list->Print();
  }

  MinidumpModuleList *module_list = minidump.GetModuleList();
  if (!module_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetModuleList() failed";
  } else {
    module_list->Print();
  }

  MinidumpMemoryList *memory_list = minidump.GetMemoryList();
  if (!memory_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetMemoryList() failed";
  } else {
    memory_list->Print();
  }

  MinidumpException *exception = minidump.GetException();
  if (!exception) {
    BPLOG(INFO) << "minidump.GetException() failed";
  } else {
    exception->Print();
  }

  MinidumpAssertion *assertion = minidump.GetAssertion();
  if (!assertion) {
    BPLOG(INFO) << "minidump.GetAssertion() failed";
  } else {
    assertion->Print();
  }

  MinidumpSystemInfo *system_info = minidump.GetSystemInfo();
  if (!system_info) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetSystemInfo() failed";
  } else {
    system_info->Print();
  }

  MinidumpMiscInfo *misc_info = minidump.GetMiscInfo();
  if (!misc_info) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetMiscInfo() failed";
  } else {
    misc_info->Print();
  }

  MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo();
  if (!breakpad_info) {
    // Breakpad info is optional, so don't treat this as an error.
    BPLOG(INFO) << "minidump.GetBreakpadInfo() failed";
  } else {
    breakpad_info->Print();
  }

  return errors == 0;
}

}  // namespace

int main(int argc, char **argv) {
  BPLOG_INIT(&argc, &argv);

  if (argc != 2) {
    fprintf(stderr, "usage: %s <file>\n", argv[0]);
    return 1;
  }

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

// minidump_dump.cc: Print the contents of a minidump file in somewhat
// readable text.
//
// Author: Mark Mentovai

#include <stdio.h>
#include <string.h>

#include "client/linux/minidump_writer/minidump_extension_linux.h"
#include "google_breakpad/processor/minidump.h"
#include "processor/logging.h"
#include "processor/scoped_ptr.h"

namespace {

using google_breakpad::Minidump;
using google_breakpad::MinidumpThreadList;
using google_breakpad::MinidumpModuleList;
using google_breakpad::MinidumpMemoryList;
using google_breakpad::MinidumpException;
using google_breakpad::MinidumpAssertion;
using google_breakpad::MinidumpSystemInfo;
using google_breakpad::MinidumpMiscInfo;
using google_breakpad::MinidumpBreakpadInfo;

static void DumpRawStream(Minidump *minidump,
                          u_int32_t stream_type,
                          const char *stream_name,
                          int *errors) {
  u_int32_t length = 0;
  if (!minidump->SeekToStreamType(stream_type, &length)) {
    return;
  }

  printf("Stream %s:\n", stream_name);

  if (length == 0) {
    printf("\n");
    return;
  }
  std::vector<char> contents(length);
  if (!minidump->ReadBytes(&contents[0], length)) {
    ++*errors;
    BPLOG(ERROR) << "minidump.ReadBytes failed";
    return;
  }
  size_t current_offset = 0;
  while (current_offset < length) {
    size_t remaining = length - current_offset;
    printf("%.*s", remaining, &contents[current_offset]);
    char *next_null = reinterpret_cast<char *>(
        memchr(&contents[current_offset], 0, remaining));
    if (next_null == NULL)
      break;
    printf("\\0\n");
    size_t null_offset = next_null - &contents[0];
    current_offset = null_offset + 1;
  }
  printf("\n\n");
}

static bool PrintMinidumpDump(const char *minidump_file) {
  Minidump minidump(minidump_file);
  if (!minidump.Read()) {
    BPLOG(ERROR) << "minidump.Read() failed";
    return false;
  }
  minidump.Print();

  int errors = 0;

  MinidumpThreadList *thread_list = minidump.GetThreadList();
  if (!thread_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetThreadList() failed";
  } else {
    thread_list->Print();
  }

  MinidumpModuleList *module_list = minidump.GetModuleList();
  if (!module_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetModuleList() failed";
  } else {
    module_list->Print();
  }

  MinidumpMemoryList *memory_list = minidump.GetMemoryList();
  if (!memory_list) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetMemoryList() failed";
  } else {
    memory_list->Print();
  }

  MinidumpException *exception = minidump.GetException();
  if (!exception) {
    BPLOG(INFO) << "minidump.GetException() failed";
  } else {
    exception->Print();
  }

  MinidumpAssertion *assertion = minidump.GetAssertion();
  if (!assertion) {
    BPLOG(INFO) << "minidump.GetAssertion() failed";
  } else {
    assertion->Print();
  }

  MinidumpSystemInfo *system_info = minidump.GetSystemInfo();
  if (!system_info) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetSystemInfo() failed";
  } else {
    system_info->Print();
  }

  MinidumpMiscInfo *misc_info = minidump.GetMiscInfo();
  if (!misc_info) {
    ++errors;
    BPLOG(ERROR) << "minidump.GetMiscInfo() failed";
  } else {
    misc_info->Print();
  }

  MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo();
  if (!breakpad_info) {
    // Breakpad info is optional, so don't treat this as an error.
    BPLOG(INFO) << "minidump.GetBreakpadInfo() failed";
  } else {
    breakpad_info->Print();
  }

  DumpRawStream(&minidump,
                MD_LINUX_CMD_LINE,
                "MD_LINUX_CMD_LINE",
                &errors);
  DumpRawStream(&minidump,
                MD_LINUX_ENVIRON,
                "MD_LINUX_ENVIRON",
                &errors);
  DumpRawStream(&minidump,
                MD_LINUX_LSB_RELEASE,
                "MD_LINUX_LSB_RELEASE",
                &errors);
  DumpRawStream(&minidump,
                MD_LINUX_PROC_STATUS,
                "MD_LINUX_PROC_STATUS",
                &errors);
  DumpRawStream(&minidump,
                MD_LINUX_CPU_INFO,
                "MD_LINUX_CPU_INFO",
                &errors);

  return errors == 0;
}

}  // namespace

int main(int argc, char **argv) {
  BPLOG_INIT(&argc, &argv);

  if (argc != 2) {
    fprintf(stderr, "usage: %s <file>\n", argv[0]);
    return 1;
  }

  return PrintMinidumpDump(argv[1]) ? 0 : 1;
}
<|endoftext|>


<commit_before>#include <annis/join/seed.h>
#include <annis/annosearch/annotationsearch.h>

using namespace annis;

AnnoKeySeedJoin::AnnoKeySeedJoin(const DB &db, std::shared_ptr<Operator> op,
                    std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                   const std::set<AnnotationKey> &rightAnnoKeys)
  : db(db), op(op), currentMatchValid(false),
    left(lhs), lhsIdx(lhsIdx), rightAnnoKeys(rightAnnoKeys)
{
  nextLeftMatch();
}

bool AnnoKeySeedJoin::next(std::vector<Match>& tuple)
{
  tuple.clear();
  bool found = false;

  if(!op || !left || !currentMatchValid || rightAnnoKeys.empty())
  {
    return false;
  }

  if(nextRightAnnotation())
  {
    tuple.reserve(currentLHSMatch.size()+1);
    tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
    tuple.push_back(currentRHSMatch);
    return true;
  }

  do
  {
    while(matchesByOperator && matchesByOperator->next(currentRHSMatch))
    {
      if(rightAnnoKeys.size() == 1)
      {
        // only check the annotation key, not the value
        const AnnotationKey& key = *(rightAnnoKeys.begin());
        std::pair<bool, Annotation> foundAnno =
            db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, key.ns, key.name);
        if(foundAnno.first && checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, foundAnno.second))
        {
          currentRHSMatch.anno = foundAnno.second;

          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);

          return true;
        }
      }
      else
      {
        // use the annotation keys as filter
        for(const auto& key : rightAnnoKeys)
        {
          std::pair<bool, Annotation> foundAnno =
              db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, key.ns, key.name);
          if(foundAnno.first)
          {
            matchingRightAnnos.push_back(foundAnno.second);
          }
        }

        if(nextRightAnnotation())
        {
          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);
          return true;
        }
      }
    } // end while there are right candidates
  } while(nextLeftMatch()); // end while left has match

  return false;
}

void AnnoKeySeedJoin::reset()
{
  if(left)
  {
    left->reset();
  }

  matchesByOperator.reset(nullptr);
  matchingRightAnnos.clear();
  currentMatchValid = false;

  // start the iterations
  nextLeftMatch();

}

bool AnnoKeySeedJoin::nextLeftMatch()
{
  matchingRightAnnos.clear();
  if(op && op->valid() && left && left->next(currentLHSMatch))
  {
    currentMatchValid = true;

    matchesByOperator = op->retrieveMatches(currentLHSMatch[lhsIdx]);
    if(matchesByOperator)
    {
      return true;
    }
  }

  return false;
}

bool AnnoKeySeedJoin::nextRightAnnotation()
{
  while(!matchingRightAnnos.empty())
  {
    if(checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, matchingRightAnnos.front()))
    {
      currentRHSMatch.anno = matchingRightAnnos.front();
      matchingRightAnnos.pop_front();

      return true;
    }
  }
  return false;
}

MaterializedSeedJoin::MaterializedSeedJoin(const DB &db, std::shared_ptr<Operator> op,
                    std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                   const std::unordered_set<Annotation>& rightAnno)
  : db(db), op(op), currentMatchValid(false),
    left(lhs), lhsIdx(lhsIdx), right(rightAnno)
{
  nextLeftMatch();
}

bool MaterializedSeedJoin::next(std::vector<Match>& tuple)
{
  tuple.clear();

  // check some conditions where we can't perform a join
  if(!op || !left || !currentMatchValid || right.empty())
  {
    return false;
  }

  if(nextRightAnnotation())
  {
    tuple.reserve(currentLHSMatch.size()+1);
    tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
    tuple.push_back(currentRHSMatch);
    return true;
  }

  do
  {
    while(matchesByOperator && matchesByOperator->next(currentRHSMatch))
    {
      if(right.size() == 1)
      {
        // directly get the one node annotation
        const auto& rightAnno = *(right.begin());
        auto foundAnno =
            db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, rightAnno.ns, rightAnno.name);
        if(foundAnno.first && foundAnno.second.val == rightAnno.val
           && checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, foundAnno.second))
        {
          currentRHSMatch.anno = foundAnno.second;

          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);

          return true;
        }
      }
      else
      {
        // check all annotations which of them matches
        std::list<Annotation> annos = db.nodeAnnos.getNodeAnnotationsByID(currentRHSMatch.node);
        for(const auto& a : annos)
        {
          if(right.find(a) != right.end())
          {
            matchingRightAnnos.push_back(a);
          }
        }

        if(nextRightAnnotation())
        {
          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);
          return true;
        }
      }
    } // end while there are right candidates
  } while(nextLeftMatch()); // end while left has match

  return false;
}

void MaterializedSeedJoin::reset()
{
  if(left)
  {
    left->reset();
  }

  matchesByOperator.reset(nullptr);
  matchingRightAnnos.clear();
  currentMatchValid = false;

  // start the iterations
  nextLeftMatch();

}

bool MaterializedSeedJoin::nextLeftMatch()
{
  matchingRightAnnos.clear();
  if(op && op->valid() && left && left->next(currentLHSMatch))
  {
    currentMatchValid = true;

    matchesByOperator = op->retrieveMatches(currentLHSMatch[lhsIdx]);
    if(matchesByOperator)
    {
      return true;
    }
  }

  return false;
}

bool MaterializedSeedJoin::nextRightAnnotation()
{
  while(matchingRightAnnos.size() > 0)
  {
    if(checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, matchingRightAnnos.front()))
    {
      currentRHSMatch.anno = matchingRightAnnos.front();
      matchingRightAnnos.pop_front();
      return true;
    }
  }
  return false;
}

<commit_msg>don't fetch any tuples in constructor of the seed join(s)<commit_after>#include <annis/join/seed.h>
#include <annis/annosearch/annotationsearch.h>

using namespace annis;

AnnoKeySeedJoin::AnnoKeySeedJoin(const DB &db, std::shared_ptr<Operator> op,
                    std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                   const std::set<AnnotationKey> &rightAnnoKeys)
  : db(db), op(op), currentMatchValid(false),
    left(lhs), lhsIdx(lhsIdx), rightAnnoKeys(rightAnnoKeys)
{

}

bool AnnoKeySeedJoin::next(std::vector<Match>& tuple)
{
  tuple.clear();
  bool found = false;

  if(!currentMatchValid)
  {
    nextLeftMatch();
  }

  if(!op || !left || !currentMatchValid || rightAnnoKeys.empty())
  {
    return false;
  }

  if(nextRightAnnotation())
  {
    tuple.reserve(currentLHSMatch.size()+1);
    tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
    tuple.push_back(currentRHSMatch);
    return true;
  }

  do
  {
    while(matchesByOperator && matchesByOperator->next(currentRHSMatch))
    {
      if(rightAnnoKeys.size() == 1)
      {
        // only check the annotation key, not the value
        const AnnotationKey& key = *(rightAnnoKeys.begin());
        std::pair<bool, Annotation> foundAnno =
            db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, key.ns, key.name);
        if(foundAnno.first && checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, foundAnno.second))
        {
          currentRHSMatch.anno = foundAnno.second;

          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);

          return true;
        }
      }
      else
      {
        // use the annotation keys as filter
        for(const auto& key : rightAnnoKeys)
        {
          std::pair<bool, Annotation> foundAnno =
              db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, key.ns, key.name);
          if(foundAnno.first)
          {
            matchingRightAnnos.push_back(foundAnno.second);
          }
        }

        if(nextRightAnnotation())
        {
          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);
          return true;
        }
      }
    } // end while there are right candidates
  } while(nextLeftMatch()); // end while left has match

  return false;
}

void AnnoKeySeedJoin::reset()
{
  if(left)
  {
    left->reset();
  }

  matchesByOperator.reset(nullptr);
  matchingRightAnnos.clear();
  currentMatchValid = false;

  // start the iterations
  nextLeftMatch();

}

bool AnnoKeySeedJoin::nextLeftMatch()
{
  matchingRightAnnos.clear();
  if(op && op->valid() && left && left->next(currentLHSMatch))
  {
    currentMatchValid = true;

    matchesByOperator = op->retrieveMatches(currentLHSMatch[lhsIdx]);
    if(matchesByOperator)
    {
      return true;
    }
  }

  return false;
}

bool AnnoKeySeedJoin::nextRightAnnotation()
{
  while(!matchingRightAnnos.empty())
  {
    if(checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, matchingRightAnnos.front()))
    {
      currentRHSMatch.anno = matchingRightAnnos.front();
      matchingRightAnnos.pop_front();

      return true;
    }
  }
  return false;
}

MaterializedSeedJoin::MaterializedSeedJoin(const DB &db, std::shared_ptr<Operator> op,
                    std::shared_ptr<Iterator> lhs, size_t lhsIdx,
                   const std::unordered_set<Annotation>& rightAnno)
  : db(db), op(op), currentMatchValid(false),
    left(lhs), lhsIdx(lhsIdx), right(rightAnno)
{
}

bool MaterializedSeedJoin::next(std::vector<Match>& tuple)
{
  tuple.clear();

  if(!currentMatchValid)
  {
    nextLeftMatch();
  }

  // check some conditions where we can't perform a join
  if(!op || !left || !currentMatchValid || right.empty())
  {
    return false;
  }

  if(nextRightAnnotation())
  {
    tuple.reserve(currentLHSMatch.size()+1);
    tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
    tuple.push_back(currentRHSMatch);
    return true;
  }

  do
  {
    while(matchesByOperator && matchesByOperator->next(currentRHSMatch))
    {
      if(right.size() == 1)
      {
        // directly get the one node annotation
        const auto& rightAnno = *(right.begin());
        auto foundAnno =
            db.nodeAnnos.getNodeAnnotation(currentRHSMatch.node, rightAnno.ns, rightAnno.name);
        if(foundAnno.first && foundAnno.second.val == rightAnno.val
           && checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, foundAnno.second))
        {
          currentRHSMatch.anno = foundAnno.second;

          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);

          return true;
        }
      }
      else
      {
        // check all annotations which of them matches
        std::list<Annotation> annos = db.nodeAnnos.getNodeAnnotationsByID(currentRHSMatch.node);
        for(const auto& a : annos)
        {
          if(right.find(a) != right.end())
          {
            matchingRightAnnos.push_back(a);
          }
        }

        if(nextRightAnnotation())
        {
          tuple.reserve(currentLHSMatch.size()+1);
          tuple.insert(tuple.end(), currentLHSMatch.begin(), currentLHSMatch.end());
          tuple.push_back(currentRHSMatch);
          return true;
        }
      }
    } // end while there are right candidates
  } while(nextLeftMatch()); // end while left has match

  return false;
}

void MaterializedSeedJoin::reset()
{
  if(left)
  {
    left->reset();
  }

  matchesByOperator.reset(nullptr);
  matchingRightAnnos.clear();
  currentMatchValid = false;

  // start the iterations
  nextLeftMatch();

}

bool MaterializedSeedJoin::nextLeftMatch()
{
  matchingRightAnnos.clear();
  if(op && op->valid() && left && left->next(currentLHSMatch))
  {
    currentMatchValid = true;

    matchesByOperator = op->retrieveMatches(currentLHSMatch[lhsIdx]);
    if(matchesByOperator)
    {
      return true;
    }
  }

  return false;
}

bool MaterializedSeedJoin::nextRightAnnotation()
{
  while(matchingRightAnnos.size() > 0)
  {
    if(checkReflexitivity(currentLHSMatch[lhsIdx].node, currentLHSMatch[lhsIdx].anno, currentRHSMatch.node, matchingRightAnnos.front()))
    {
      currentRHSMatch.anno = matchingRightAnnos.front();
      matchingRightAnnos.pop_front();
      return true;
    }
  }
  return false;
}

<|endoftext|>