/* -*- C++ -*-
 * src/test/graph_test.h - Part of LEMON, a generic C++ optimization library
 *
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 * (Egervary Combinatorial Optimization Research Group, EGRES).
 *
 * Permission to use, modify and distribute this software is granted
 * provided that this copyright notice appears in all copies. For
 * precise terms see the accompanying LICENSE file.
 *
 * This software is provided "AS IS" with no warranty of any kind,
 * express or implied, and with no claim as to its suitability for any
 * purpose.
 *
 */
#ifndef LEMON_TEST_GRAPH_TEST_H
#define LEMON_TEST_GRAPH_TEST_H


#include "test_tools.h"

//! \ingroup misc
//! \file
//! \brief Some utility to  test graph classes.
namespace lemon {

  struct DummyType {
    int value;
    DummyType() {}
    DummyType(int p) : value(p) {}
    DummyType& operator=(int p) { value = p; return *this;}
  };


  template<class Graph> void checkCompileStaticGraph(Graph &G) 
    {
      typedef typename Graph::Node Node;
      typedef typename Graph::NodeIt NodeIt;
      typedef typename Graph::Edge Edge;
      typedef typename Graph::EdgeIt EdgeIt;
      typedef typename Graph::InEdgeIt InEdgeIt;
      typedef typename Graph::OutEdgeIt OutEdgeIt;
  
      {
	Node i; Node j(i); Node k(INVALID);
	i=j;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	b=(i==j); b=(i!=j); b=(i<j);
      }
      {
	NodeIt i; NodeIt j(i); NodeIt k(INVALID); NodeIt l(G);
	i=j;
	j=G.first(i);
	j=++i;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	Node n(i);
	n=i;
	b=(i==j); b=(i!=j); b=(i<j);
	//Node ->NodeIt conversion
	NodeIt ni(G,n);
      }
      {
	Edge i; Edge j(i); Edge k(INVALID);
	i=j;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	b=(i==j); b=(i!=j); b=(i<j);
      }
      {
	EdgeIt i; EdgeIt j(i); EdgeIt k(INVALID); EdgeIt l(G);
	i=j;
	j=G.first(i);
	j=++i;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	Edge e(i);
	e=i;
	b=(i==j); b=(i!=j); b=(i<j);
	//Edge ->EdgeIt conversion
	EdgeIt ei(G,e);
      }
      {
	Node n;
	InEdgeIt i; InEdgeIt j(i); InEdgeIt k(INVALID); InEdgeIt l(G,n);
	i=j;
	j=G.first(i,n);
	j=++i;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	Edge e(i);
	e=i;
	b=(i==j); b=(i!=j); b=(i<j);
	//Edge ->InEdgeIt conversion
	InEdgeIt ei(G,e);
      }
      {
	Node n;
	OutEdgeIt i; OutEdgeIt j(i); OutEdgeIt k(INVALID); OutEdgeIt l(G,n);
	i=j;
	j=G.first(i,n);
	j=++i;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	Edge e(i);
	e=i;
	b=(i==j); b=(i!=j); b=(i<j);
	//Edge ->OutEdgeIt conversion
	OutEdgeIt ei(G,e);
      }
      {
	Node n,m;
	n=m=INVALID;
	Edge e;
	e=INVALID;
	n=G.tail(e);
	n=G.head(e);
      }
      // id tests
      { Node n; int i=G.id(n); i=i; }
      { Edge e; int i=G.id(e); i=i; }
      //NodeMap tests
      {
	Node k;
	typename Graph::template NodeMap<int> m(G);
	//Const map
	typename Graph::template NodeMap<int> const &cm = m;
	//Inicialize with default value
	typename Graph::template NodeMap<int> mdef(G,12);
	//Copy
	typename Graph::template NodeMap<int> mm(cm);
	//Copy from another type
	typename Graph::template NodeMap<double> dm(cm);
	//Copy to more complex type
	typename Graph::template NodeMap<DummyType> em(cm);
	int v;
	v=m[k]; m[k]=v; m.set(k,v);
	v=cm[k];
    
	m=cm;  
	dm=cm; //Copy from another type  
	em=cm; //Copy to more complex type
	{
	  //Check the typedef's
	  typename Graph::template NodeMap<int>::ValueType val;
	  val=1;
	  typename Graph::template NodeMap<int>::KeyType key;
	  key = typename Graph::NodeIt(G);
	}
      }  
      { //bool NodeMap
	Node k;
	typename Graph::template NodeMap<bool> m(G);
	typename Graph::template NodeMap<bool> const &cm = m;  //Const map
	//Inicialize with default value
	typename Graph::template NodeMap<bool> mdef(G,12);
	typename Graph::template NodeMap<bool> mm(cm);   //Copy
	typename Graph::template NodeMap<int> dm(cm); //Copy from another type
	bool v;
	v=m[k]; m[k]=v; m.set(k,v);
	v=cm[k];
    
	m=cm;  
	dm=cm; //Copy from another type
	m=dm; //Copy to another type

	{
	  //Check the typedef's
	  typename Graph::template NodeMap<bool>::ValueType val;
	  val=true;
	  typename Graph::template NodeMap<bool>::KeyType key;
	  key= typename Graph::NodeIt(G);
	}
      }
      //EdgeMap tests
      {
	Edge k;
	typename Graph::template EdgeMap<int> m(G);
	typename Graph::template EdgeMap<int> const &cm = m;  //Const map
	//Inicialize with default value
	typename Graph::template EdgeMap<int> mdef(G,12);
	typename Graph::template EdgeMap<int> mm(cm);   //Copy
	typename Graph::template EdgeMap<double> dm(cm); //Copy from another type
	int v;
	v=m[k]; m[k]=v; m.set(k,v);
	v=cm[k];
    
	m=cm;  
	dm=cm; //Copy from another type
	{
	  //Check the typedef's
	  typename Graph::template EdgeMap<int>::ValueType val;
	  val=1;
	  typename Graph::template EdgeMap<int>::KeyType key;
	  key= typename Graph::EdgeIt(G);
	}
      }  
      { //bool EdgeMap
	Edge k;
	typename Graph::template EdgeMap<bool> m(G);
	typename Graph::template EdgeMap<bool> const &cm = m;  //Const map
	//Inicialize with default value
	typename Graph::template EdgeMap<bool> mdef(G,12);
	typename Graph::template EdgeMap<bool> mm(cm);   //Copy
	typename Graph::template EdgeMap<int> dm(cm); //Copy from another type
	bool v;
	v=m[k]; m[k]=v; m.set(k,v);
	v=cm[k];
    
	m=cm;  
	dm=cm; //Copy from another type
	m=dm; //Copy to another type
	{
	  //Check the typedef's
	  typename Graph::template EdgeMap<bool>::ValueType val;
	  val=true;
	  typename Graph::template EdgeMap<bool>::KeyType key;
	  key= typename Graph::EdgeIt(G);
	}
      }
    }

  template<class Graph> void checkCompileGraph(Graph &G) 
    {
      checkCompileStaticGraph(G);

      typedef typename Graph::Node Node;
      typedef typename Graph::NodeIt NodeIt;
      typedef typename Graph::Edge Edge;
      typedef typename Graph::EdgeIt EdgeIt;
      typedef typename Graph::InEdgeIt InEdgeIt;
      typedef typename Graph::OutEdgeIt OutEdgeIt;
  
      Node n,m;
      n=G.addNode();
      m=G.addNode();
      Edge e;
      e=G.addEdge(n,m); 
  
      //  G.clear();
    }

  template<class Graph> void checkCompileGraphEraseEdge(Graph &G) 
    {
      typename Graph::Edge e;
      G.erase(e);
    }

  template<class Graph> void checkCompileGraphEraseNode(Graph &G) 
    {
      typename Graph::Node n;
      G.erase(n);
    }

  template<class Graph> void checkCompileErasableGraph(Graph &G) 
    {
      checkCompileGraph(G);
      checkCompileGraphEraseNode(G);
      checkCompileGraphEraseEdge(G);
    }

  template<class Graph> void checkCompileGraphFindEdge(Graph &G) 
    {
      typedef typename Graph::NodeIt Node;
      typedef typename Graph::NodeIt NodeIt;

      G.findEdge(NodeIt(G),++NodeIt(G),G.findEdge(NodeIt(G),++NodeIt(G)));
      G.findEdge(Node(),Node(),G.findEdge(Node(),Node()));  
    }

  template<class Graph> void checkGraphNodeList(Graph &G, int nn)
    {
      typename Graph::NodeIt n(G);
      for(int i=0;i<nn;i++) {
	check(n!=INVALID,"Wrong Node list linking.");
	++n;
      }
      check(n==INVALID,"Wrong Node list linking.");
    }

  template<class Graph> void checkGraphEdgeList(Graph &G, int nn)
    {
      typedef typename Graph::EdgeIt EdgeIt;

      EdgeIt e(G);
      for(int i=0;i<nn;i++) {
	check(e!=INVALID,"Wrong Edge list linking.");
	++e;
      }
      check(e==INVALID,"Wrong Edge list linking.");
    }

  template<class Graph> void checkGraphOutEdgeList(Graph &G,
						   typename Graph::Node n,
						   int nn)
    {
      typename Graph::OutEdgeIt e(G,n);
      for(int i=0;i<nn;i++) {
	check(e!=INVALID,"Wrong OutEdge list linking.");
	++e;
      }
      check(e==INVALID,"Wrong OutEdge list linking.");
    }

  template<class Graph> void checkGraphInEdgeList(Graph &G,
						  typename Graph::Node n,
						  int nn)
    {
      typename Graph::InEdgeIt e(G,n);
      for(int i=0;i<nn;i++) {
	check(e!=INVALID,"Wrong InEdge list linking.");
	++e;
      }
      check(e==INVALID,"Wrong InEdge list linking.");
    }

  ///\file
  ///\todo Check head(), tail() as well;

  
} //namespace lemon


#endif
