// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
// .NAME TestStructuredAMRNeighbor.cxx -- Test vtkStructuredAMRNeighbor
//
// .SECTION Description
//  A simple test for structured AMR neighbor

// C++ includes
#include <iostream>
#include <sstream>
#include <string>

// VTK includes
#include "vtkStructuredAMRNeighbor.h"

#define IMIN(ext) ext[0]
#define IMAX(ext) ext[1]
#define JMIN(ext) ext[2]
#define JMAX(ext) ext[3]
#define KMIN(ext) ext[4]
#define KMAX(ext) ext[5]

std::string StringExtent(int ext[6])
{
  std::ostringstream oss;
  oss.clear();
  oss.str("");
  for (int i = 0; i < 3; ++i)
  {
    oss << "[" << ext[i * 2] << " " << ext[i * 2 + 1] << "] ";
  }
  return (oss.str());
}

//------------------------------------------------------------------------------
int CheckExtents(int ext[6], int exp[6])
{
  std::cout << "CHECKING EXTENT: " << StringExtent(ext);
  std::cout << "EXPECTED EXTENT: " << StringExtent(exp);
  std::cout << "...";
  std::cout.flush();
  for (int i = 0; i < 6; ++i)
  {
    if (ext[i] != exp[i])
    {
      std::cout << "[ERROR]\n";
      std::cout.flush();
      return 1;
    } // END if
  }   // END for
  std::cout << "[OK]\n";
  std::cout.flush();
  return 0;
}

//------------------------------------------------------------------------------
int TestParentNeighbor()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::PARENT;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 1;
  int neiLevel = 0;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = JMIN(gridExtent) = 4;
  IMAX(gridExtent) = JMAX(gridExtent) = 10;

  IMIN(neiExtent) = JMIN(neiExtent) = 0;
  IMAX(neiExtent) = JMAX(neiExtent) = 8;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = JMIN(gridOverlap) = 4;
  IMAX(gridOverlap) = JMAX(gridOverlap) = 10;

  IMIN(neiOverlap) = JMIN(neiOverlap) = 2;
  IMAX(neiOverlap) = JMAX(neiOverlap) = 5;

  // STEP 3: Setup orientation tuple
  orientation[0] = orientation[1] = vtkStructuredNeighbor::SUBSET_BOTH;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = JMIN(ExpectedSendExtent) = 4;
  IMAX(ExpectedSendExtent) = JMAX(ExpectedSendExtent) = 10;

  IMIN(ExpectedRcvExtent) = JMIN(ExpectedRcvExtent) = 1;
  IMAX(ExpectedRcvExtent) = JMAX(ExpectedRcvExtent) = 6;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestPartiallyOverlappingParent()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::PARTIALLY_OVERLAPPING_PARENT;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 1;
  int neiLevel = 0;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = JMIN(gridExtent) = 4;
  IMAX(gridExtent) = JMAX(gridExtent) = 10;

  IMIN(neiExtent) = JMIN(neiExtent) = 0;
  IMAX(neiExtent) = 3;
  JMAX(neiExtent) = 8;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = JMIN(gridOverlap) = 4;
  IMAX(gridOverlap) = 6;
  JMAX(gridOverlap) = 10;

  IMIN(neiOverlap) = JMIN(neiOverlap) = 2;
  IMAX(neiOverlap) = 3;
  JMAX(neiOverlap) = 5;

  // STEP 3: Setup orientation tuple
  orientation[0] = vtkStructuredNeighbor::SUBSET_LO;
  orientation[1] = vtkStructuredNeighbor::SUBSET_BOTH;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = JMIN(ExpectedSendExtent) = 4;
  IMAX(ExpectedSendExtent) = 7;
  JMAX(ExpectedSendExtent) = 10;

  IMIN(ExpectedRcvExtent) = JMIN(ExpectedRcvExtent) = 1;
  IMAX(ExpectedRcvExtent) = 3;
  JMAX(ExpectedRcvExtent) = 6;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestChildNeighbor()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::CHILD;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 0;
  int neiLevel = 1;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = JMIN(gridExtent) = 0;
  IMAX(gridExtent) = JMAX(gridExtent) = 8;

  IMIN(neiExtent) = JMIN(neiExtent) = 4;
  IMAX(neiExtent) = JMAX(neiExtent) = 10;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = JMIN(gridOverlap) = 2;
  IMAX(gridOverlap) = JMAX(gridOverlap) = 5;

  IMIN(neiOverlap) = JMIN(neiOverlap) = 4;
  IMAX(neiOverlap) = JMAX(neiOverlap) = 10;

  // STEP 3: Setup orientation tuple
  orientation[0] = orientation[1] = vtkStructuredNeighbor::SUPERSET;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = JMIN(ExpectedSendExtent) = 1;
  IMAX(ExpectedSendExtent) = JMAX(ExpectedSendExtent) = 6;

  IMIN(ExpectedRcvExtent) = JMIN(ExpectedRcvExtent) = 4;
  IMAX(ExpectedRcvExtent) = JMAX(ExpectedRcvExtent) = 10;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestPartiallyOverlappingChild()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::PARTIALLY_OVERLAPPING_CHILD;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 0;
  int neiLevel = 1;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = JMIN(gridExtent) = 0;
  IMAX(gridExtent) = 3;
  JMAX(gridExtent) = 8;

  IMIN(neiExtent) = JMIN(neiExtent) = 4;
  IMAX(neiExtent) = JMAX(neiExtent) = 10;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = JMIN(gridOverlap) = 2;
  IMAX(gridOverlap) = 3;
  JMAX(gridOverlap) = 5;

  IMIN(neiOverlap) = JMIN(neiOverlap) = 4;
  IMAX(neiOverlap) = 6;
  JMAX(neiOverlap) = 10;

  // STEP 3: Setup orientation tuple
  orientation[0] = vtkStructuredNeighbor::SUBSET_HI;
  orientation[1] = vtkStructuredNeighbor::SUPERSET;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = JMIN(ExpectedSendExtent) = 1;
  IMAX(ExpectedSendExtent) = 3;
  JMAX(ExpectedSendExtent) = 6;

  IMIN(ExpectedRcvExtent) = JMIN(ExpectedRcvExtent) = 4;
  IMAX(ExpectedRcvExtent) = 7;
  JMAX(ExpectedRcvExtent) = 10;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestSameLevelSibling()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::SAME_LEVEL_SIBLING;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 1;
  int neiLevel = 1;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = 10;
  JMIN(gridExtent) = 8;
  IMAX(gridExtent) = JMAX(gridExtent) = 14;

  IMIN(neiExtent) = JMIN(neiExtent) = 4;
  IMAX(neiExtent) = JMAX(neiExtent) = 10;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = IMAX(gridOverlap) = 10;
  JMIN(gridOverlap) = 8;
  JMAX(gridOverlap) = 10;

  IMIN(neiOverlap) = IMAX(neiOverlap) = 10;
  JMIN(neiOverlap) = 8;
  JMAX(neiOverlap) = 10;

  // STEP 3: Setup orientation tuple
  orientation[0] = vtkStructuredNeighbor::LO;
  orientation[1] = vtkStructuredNeighbor::SUBSET_LO;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = 10;
  JMIN(ExpectedSendExtent) = 8;
  IMAX(ExpectedSendExtent) = 11;
  JMAX(ExpectedSendExtent) = 11;

  IMIN(ExpectedRcvExtent) = 9;
  JMIN(ExpectedRcvExtent) = 7;
  IMAX(ExpectedRcvExtent) = JMAX(ExpectedRcvExtent) = 10;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestCoarseToFineNeighbor()
{

  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::COARSE_TO_FINE_SIBLING;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 0;
  int neiLevel = 1;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = JMIN(gridExtent) = 0;
  IMAX(gridExtent) = JMAX(gridExtent) = 2;

  IMIN(neiExtent) = 4;
  JMIN(neiExtent) = 0;
  IMAX(neiExtent) = 8;
  JMAX(neiExtent) = 4;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = IMAX(gridOverlap) = 2;
  JMIN(gridOverlap) = 0;
  JMAX(gridOverlap) = 2;

  IMIN(neiOverlap) = IMAX(neiOverlap) = 4;
  JMIN(neiOverlap) = 0;
  JMAX(neiOverlap) = 4;

  // STEP 3: Setup orientation tuple
  orientation[0] = vtkStructuredNeighbor::HI;
  orientation[1] = vtkStructuredNeighbor::ONE_TO_ONE;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = 1;
  JMIN(ExpectedSendExtent) = 0;
  IMAX(ExpectedSendExtent) = 2;
  JMAX(ExpectedSendExtent) = 2;

  IMIN(ExpectedRcvExtent) = 4;
  JMIN(ExpectedRcvExtent) = 0;
  IMAX(ExpectedRcvExtent) = 5;
  JMAX(ExpectedRcvExtent) = 4;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestFineToCoarseNeighbor()
{
  int rc = 0;

  int relationship = vtkStructuredAMRNeighbor::FINE_TO_COARSE_SIBLING;

  // STEP 0: initialize AMR neighbor parameters
  const int NG = 1;

  int wholeExtent[6];
  int gridExtent[6];
  int neiExtent[6];
  KMIN(wholeExtent) = KMAX(wholeExtent) = KMIN(gridExtent) = KMAX(gridExtent) = KMIN(neiExtent) =
    KMAX(neiExtent) = 0;

  int gridLevel = 1;
  int neiLevel = 0;
  int orientation[3];
  orientation[2] = vtkStructuredNeighbor::UNDEFINED;

  int gridOverlap[6];
  int neiOverlap[6];
  KMIN(gridOverlap) = KMAX(gridOverlap) = KMIN(neiOverlap) = KMAX(neiOverlap) = 0;

  int ExpectedSendExtent[6];
  int ExpectedRcvExtent[6];
  KMIN(ExpectedSendExtent) = KMAX(ExpectedSendExtent) = KMIN(ExpectedRcvExtent) =
    KMAX(ExpectedRcvExtent) = 0;

  // STEP 1: Setup grid extents and whole extent
  IMIN(gridExtent) = 4;
  JMIN(gridExtent) = 0;
  IMAX(gridExtent) = 8;
  JMAX(gridExtent) = 4;

  IMIN(neiExtent) = JMIN(neiExtent) = 0;
  IMAX(neiExtent) = JMAX(neiExtent) = 2;

  IMIN(wholeExtent) = JMIN(wholeExtent) = 0;
  IMAX(wholeExtent) = JMAX(wholeExtent) = 8;

  // STEP 2: Setup overlap extents
  IMIN(gridOverlap) = IMAX(gridOverlap) = 4;
  JMIN(gridOverlap) = 0;
  JMAX(gridOverlap) = 4;

  IMIN(neiOverlap) = IMAX(neiOverlap) = 2;
  JMIN(neiOverlap) = 0;
  JMAX(neiOverlap) = 2;

  // STEP 3: Setup orientation tuple
  orientation[0] = vtkStructuredNeighbor::LO;
  orientation[1] = vtkStructuredNeighbor::ONE_TO_ONE;

  // STEP 4: Setup expected send/rcv extents
  IMIN(ExpectedSendExtent) = 4;
  JMIN(ExpectedSendExtent) = 0;
  IMAX(ExpectedSendExtent) = 5;
  JMAX(ExpectedSendExtent) = 4;

  IMIN(ExpectedRcvExtent) = 1;
  JMIN(ExpectedRcvExtent) = 0;
  IMAX(ExpectedRcvExtent) = 2;
  JMAX(ExpectedRcvExtent) = 2;

  // STEP 5: Setup AMR neighbor
  vtkStructuredAMRNeighbor amrnei(
    gridLevel, 0, neiLevel, gridOverlap, neiOverlap, orientation, relationship);

  // STEP 6: Compute send/receive extents
  amrnei.ComputeSendAndReceiveExtent(gridExtent, gridExtent, neiExtent, wholeExtent, NG);

  // STEP 7: Check expected extents
  rc += CheckExtents(amrnei.SendExtent, ExpectedSendExtent);
  rc += CheckExtents(amrnei.RcvExtent, ExpectedRcvExtent);
  return (rc);
}

//------------------------------------------------------------------------------
int TestAssignmentOperator()
{
  int rc = 0;

  // Allocate A with default values
  vtkStructuredAMRNeighbor A;
  if (A.GetRelationShipString() != "UNDEFINED")
  {
    ++rc;
  }

  // Allocate B and set some ivars arbitrarily
  vtkStructuredAMRNeighbor B;
  B.GridLevel = B.NeighborLevel = 100;
  B.RelationShip = vtkStructuredAMRNeighbor::SAME_LEVEL_SIBLING;
  if (B.GetRelationShipString() != "SAME_LEVEL_SIBLING")
  {
    ++rc;
  }

  // Reset B to initial
  B = A;

  // Ensure initial values for ivars
  if (B.GridLevel != -1)
  {
    ++rc;
  }
  if (B.NeighborLevel != -1)
  {
    ++rc;
  }
  if (B.RelationShip != vtkStructuredAMRNeighbor::UNDEFINED)
  {
    ++rc;
  }
  return (rc);
}

//------------------------------------------------------------------------------
int TestGetRelationShipString()
{
  int rc = 0;
  vtkStructuredAMRNeighbor A;
  A.RelationShip = vtkStructuredAMRNeighbor::PARENT;
  if (A.GetRelationShipString() != "PARENT")
  {
    std::cerr << "Expected PARENT\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::PARTIALLY_OVERLAPPING_PARENT;
  if (A.GetRelationShipString() != "PARTIALLY_OVERLAPPING_PARENT")
  {
    std::cerr << "Expected PARTIALY_OVERLAPPING_PARENT\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::CHILD;
  if (A.GetRelationShipString() != "CHILD")
  {
    std::cerr << "Expected CHILD\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::PARTIALLY_OVERLAPPING_CHILD;
  if (A.GetRelationShipString() != "PARTIALLY_OVERLAPPING_CHILD")
  {
    std::cerr << "Expected PARTIALLY_OVERLAPPING_CHILD\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::SAME_LEVEL_SIBLING;
  if (A.GetRelationShipString() != "SAME_LEVEL_SIBLING")
  {
    std::cerr << "Expected SAME_LEVEL_SIBLING\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::COARSE_TO_FINE_SIBLING;
  if (A.GetRelationShipString() != "COARSE_TO_FINE_SIBLING")
  {
    std::cerr << "Expected COARSE_TO_FINE_SIBLING\n";
    ++rc;
  }

  A.RelationShip = vtkStructuredAMRNeighbor::FINE_TO_COARSE_SIBLING;
  if (A.GetRelationShipString() != "FINE_TO_COARSE_SIBLING")
  {
    std::cerr << "Expected FINE_TO_COARSE_SIBLING\n";
    ++rc;
  }

  return (rc);
}

//------------------------------------------------------------------------------
int TestStructuredAMRNeighbor(int argc, char* argv[])
{
  // Silence compiler warnings
  static_cast<void>(argc);
  static_cast<void>(argv);

  int rc = 0;
  rc += TestParentNeighbor();
  rc += TestPartiallyOverlappingParent();
  rc += TestChildNeighbor();
  rc += TestPartiallyOverlappingChild();
  rc += TestSameLevelSibling();
  rc += TestCoarseToFineNeighbor();
  rc += TestCoarseToFineNeighbor();
  rc += TestFineToCoarseNeighbor();
  rc += TestAssignmentOperator();
  rc += TestGetRelationShipString();
  return (rc);
}
