/* -*- C++ -*-
 * src/test/sym_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_SYM_GRAPH_TEST_H
#define LEMON_TEST_SYM_GRAPH_TEST_H


#include "graph_test.h"
#include "test_tools.h"

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

  /// \todo This should go to lemon/concept/symgraph.h
  ///
  template<class Graph> void checkCompileStaticSymGraph(Graph &G) 
    {
      typedef typename Graph::Node Node;
      typedef typename Graph::NodeIt NodeIt;
      typedef typename Graph::SymEdge SymEdge;
      typedef typename Graph::SymEdgeIt SymEdgeIt;
      typedef typename Graph::Edge Edge;
      typedef typename Graph::EdgeIt EdgeIt;
      typedef typename Graph::InEdgeIt InEdgeIt;
      typedef typename Graph::OutEdgeIt OutEdgeIt;

      lemon::concept::checkCompileStaticGraph(G);
  
      {
	SymEdge i; SymEdge j(i); SymEdge k(INVALID);
	i=j;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	b=(i==j); b=(i!=j); b=(i<j);
	Edge e;
	e = G.forward(i);
	e = G.backward(i);
      }
      {
	SymEdgeIt i; SymEdgeIt j(i); SymEdgeIt k(INVALID); SymEdgeIt l(G);
	i=j;
	j=G.first(i);
	j=++i;
	bool b; b=true;
	b=(i==INVALID); b=(i!=INVALID);
	SymEdge n(i);
	n=i;
	b=(i==j); b=(i!=j); b=(i<j);
	//SymEdge ->SymEdgeIt conversion
	SymEdgeIt ni(G,n);
      }
      {
	Edge i, j;
	j = G.opposite(i);
      }      
      {
	Node n;
	SymEdge se;
	se=INVALID;
	n=G.tail(se);
	n=G.head(se);
      }
      // id tests
      { SymEdge n; int i=G.id(n); i=i; }
      //SymEdgeMap tests
      {
	SymEdge k;
	typename Graph::template SymEdgeMap<int> m(G);
	typename Graph::template SymEdgeMap<int> const &cm = m;  //Const map
	//Inicialize with default value
	typename Graph::template SymEdgeMap<int> mdef(G,12);
	typename Graph::template SymEdgeMap<int> mm(cm);   //Copy
	typename Graph::template SymEdgeMap<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 SymEdgeMap<int>::ValueType val;
	  val = 1;
	  typename Graph::template SymEdgeMap<int>::KeyType key;
	  key = typename Graph::SymEdgeIt(G);
	}
      }  
      { //bool SymEdgeMap
	SymEdge k;
	typename Graph::template SymEdgeMap<bool> m(G);
	typename Graph::template SymEdgeMap<bool> const &cm = m;  //Const map
	//Inicialize with default value
	typename Graph::template SymEdgeMap<bool> mdef(G,12);
	typename Graph::template SymEdgeMap<bool> mm(cm);   //Copy
	typename Graph::template SymEdgeMap<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 SymEdgeMap<bool>::ValueType val;
	  val=true;
	  typename Graph::template SymEdgeMap<bool>::KeyType key;
	  key= typename Graph::SymEdgeIt(G);
	}
      }
    }

  template<class Graph> void checkCompileSymGraph(Graph &G) 
    {
      checkCompileStaticSymGraph(G);

      typedef typename Graph::Node Node;
      typedef typename Graph::NodeIt NodeIt;
      typedef typename Graph::SymEdge SymEdge;
      typedef typename Graph::SymEdgeIt SymEdgeIt;
      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();
      SymEdge e;
      e = G.addEdge(n,m); 
  
      //  G.clear();
    }

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

  template<class Graph> void checkCompileErasableSymGraph(Graph &G) 
    {
      checkCompileSymGraph(G);
      lemon::concept::checkCompileGraphEraseNode(G);
      checkCompileSymGraphEraseSymEdge(G);
    }

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

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

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

  
} //namespace lemon


#endif
