#include<iostream>
#include<cmath>
 
using namespace std;
const double EPS=1e-9;
const double PI=3.141592653589793238;//18 ragham
bool Equal(double d1,double d2)
{ return fabs(d1-d2)<EPS;}
 
struct line{double a,b,c;};
struct vec
{
  double x,y;
  vec(double _x=0,double _y=0)
  {x=_x;  y=_y;}
};
   
struct point_i
{
  int x,y;
  point_i(int _x=0,int _y=0){x=_x;y=_y;}
};
struct point
{
  double x,y;
  point(double _x=0,double _y=0){x=_x;y=_y;}
  bool operator < (point other)
  {  
    if(fabs(x-other.x)<EPS)
      return y<other.y;
    return x<other.x;}
  bool operator == (point other)
  {return (fabs(x-other.x)<EPS) && (fabs(y-other.y)<EPS) ;}
   
   
};
double Hypot(double dx,double dy)
{
  return sqrt(dx*dx+dy*dy);
}
double Distance(point p1,point p2)
{
  return hypot(p1.x-p2.x,p1.y-p2.y);
}
double DEG_to_RAD(double theta)
{
  return theta*PI/180;
}
point rotate(point p, double theta)//theta is degree
{
   
  //rotation matrixR(theta) = [cos(theta) - sin(theta)]
  //                          [sin(theta) + cos(theta)]
  //usage: [x'] = R(theta)* [x]
  //       [y']             [y]
  double rad=DEG_to_RAD(theta);
  return point(p.x * cos(rad) - p.x * sin(rad) ,
           p.y * sin(rad) + p.y * cos(rad)  );
}
void PointsToLine(point p1,point p2,line *l)
{
  if(p1.x==p2.x) // vertical line handled here
    { l->a=1.0;   l->b= 0.0 ; l->c=-p1.x;}
  else
    {
      l->a=-(double)(p1.y-p2.y)/(p1.x-p2.x);
      l->b=1.0;
      l->c=-(double)(l->a * p1.x) - (l->b*p1.y);
    }
}
bool AreParallel(line l1,line l2)
{
  if(Equal(l2.b,0) && !Equal(l1.b,0))return false;
  if(Equal(l1.b,0) && !Equal(l2.b,0))return false;
  if(Equal(l2.a,0) && !Equal(l1.a,0))return false;
  if(Equal(l1.a,0) && !Equal(l2.a,0))return false;
  return Equal(l1.a*l2.b,l1.b*l2.a);
}
bool AreSame(line l1,line l2)
{
  if(!AreParallel(l1,l2))return false;
  if(Equal(l2.c,0) && !Equal(l1.c,0))return false;
  if(Equal(l1.c,0) && !Equal(l2.c,0))return false;
  double ratio=0;
  if(Equal(l2.b,0)==false)
    ratio=l1.b/l2.b;
  if(Equal(l2.a,0)==false)
    ratio=l1.a/l2.a;
  return Equal(l1.c/l2.c,ratio);
}
bool AreIntersect(line l1,line l2,point *p)//TO BE CHECKED (mine)
{
  if(AreSame(l1,l2))
    return false;
  if(AreParallel(l1,l2))
    return false;
 
  //solving
  double delta=(double)l1.a*l2.b - l1.b*l2.a;
  if(Equal(delta,0))//this if should never be true because lines are't parallel
    return false;
  p->x= (double)(l1.c*l2.b-l2.c*l1.b) / delta;
  p->y= (double)(l1.a*l2.c-l2.a*l1.c) / delta;
  return true;
}
vec ToVector(point p1,point p2)
{
  return vec(p2.x-p1.x,p2.y-p1.y);
}
vec ScaleVector(vec v, double s) // v*=s
{
  return vec(v.x*s,v.y*s);
}
point Translate(point p,vec move)//moves point p in direction of vector move
{
  return point(p.x+move.x , p.y + move.y);
}
double Dot(double x1,double y1 ,double x2,double y2)
{ return x1*x2+y1*y2;};
double Cross(point p,point q,point r)
{
  return (r.x-q.x)*(p.y-q.y)-(r.y-q.y)*(p.x-q.x);
}
bool Collinear(point p,point q,point r)
{
  return Equal(Cross(p,q,r),0);
}
//returns true if point r is on the left side of line pq
bool CCW(point p,point q,point r)
{
   //can be modified to accept collinear ( >0 instead of >EPS )
  if(Cross(p,q,r) > EPS)
    return true;
  return false;
}
///*****************### End of Library ###*******************///
 
 
 
 
 
 
 
point p1,p2,q1,q2;
 
int main()
{
  int n;
  cin>>n;
  while(n--)
    {
      int x,y;
      cin>>x>>y;
      p1=point(x,y);
      cin>>x>>y;
      p2=point(x,y);
      cin>>x>>y;
      q1=point(x,y);
      cin>>x>>y;
      q2=point(x,y);
      vec v1=ToVector(p1,p2);
      vec v2=ToVector(q1,q2);
 
       
      line l1;
      PointsToLine(p1,p2,&l1);
      line l2;
      PointsToLine(q1,q2,&l2);
      //cout<<"aa "<<l1.a<<" "<<l1.b<<" "<<l1.c<<endl;
      if(Equal(Dot(v1.x,v1.y , v2.x,v2.y),0))
    cout<<1<<endl;
      else if(AreParallel(l1,l2))
    cout<<2<<endl;
      else
    cout<<0<<endl;
    }
   
  return 0;
}

Measured memory_bytes: 1164