#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <cmath>
#include <vector>
#include <numeric>
#include <cstdio>
#include <bitset>
#include <map>
#include <string>
#include <valarray>
#include <queue>
#include <utility>
#include <functional>
#include <list>


using namespace std;

const double ESP = 1E-8;

struct Point
{
    //friends
    friend Point operator*(double c, const Point & p);
    friend ostream & operator<<(ostream & os, const Point & p);
    friend istream & operator>>(istream & is, Point & p);
    friend double cross(const Point & p1, const Point & p2);

  
    //members
    double x, y;

    Point() {};
    Point(double x, double y): x(x), y(y) {};

    Point operator-(const Point & p) const
    {
        return Point(x - p.x, y - p.y);
    }

    double operator*(const Point & p) const
    {
        return x*p.x + y*p.y;
    }

    Point operator*(double c) const
    {
        return Point(c*x, c*y);
    }

    Point operator+(const Point & p) const
    {
        return Point(x+p.x, y+p.y);
    }

    Point projection(const Point & p1, const Point & p2) const
    {
        Point a(*this-p1), b(p2-p1);
        return (a*b)/(b*b)*b+p1;
    }

    Point reflection(const Point & p1, const Point & p2) const
    {
        return this->projection(p1, p2)*2 - *this;
    }

};


struct Line
{
    Line() = default;
    Line(const Point & p1, const Point & p2): 
        direction(p1-p2), point_online(p1) {}; 
    Point direction, point_online;
    Point get_normal() const
    {
        return Point(direction.y, -direction.x);
    }
};

struct Segment
{
    Segment() = default;
    Segment(const Point & p1, const Point & p2): 
        first_end(p1), second_end(p2), direction(p2-p1), 
        length(sqrt(direction*direction)), a(direction.y), 
        b(-direction.x), c(direction.x*p1.y-direction.y*p1.x)
        {/*norm(p2-p1);*/};
    Point get_normal() const
    {
        return Point(direction.y, -direction.x);
    }

    Point first_end, second_end, direction;
    double length, a, b, c;
};


//function related with point
double norm(const Point & p);
bool check_clockwise(const Point & p0, const Point & p1, const Point & p2);
bool check_counter_clockwise(const Point & p0, const Point & p1, const Point & p2);
bool check_online_back(const Point & p0, const Point & p1, const Point & p2);
bool check_online_front(const Point & p0, const Point & p1, const Point & p2);
bool check_on_segment(const Point & p0, const Point & p1, const Point & p2);
// bool check_parallel(const Point & p0, const Point & p1, const Point & p2, const Point & p3);


//functions related with lines
bool check_parallel(const Line & l1, const Line & l2);
bool check_orthogonal(const Line & l1, const Line & l2);
bool check_intersection(const Segment & s1, const Segment & s2);
Point get_cross_point(const Segment & s1, const Segment & s2);
double distance_segment_to_segment(const Segment & s1, const Segment & s2);


int main()
{
    Point p0, p1, p2, p3;

    int q;
    cin >> q;

    int result;

    for (int i = 0; i < q; i++)
    {
        cin >> p0 >> p1 >> p2 >> p3;

        cout << setprecision(8) << fixed << distance_segment_to_segment(Segment(p0, p1), Segment(p2, p3)) << endl;
    }

}


//friends
Point operator*(double c, const Point & p)
{
    return p*c;
}

ostream & operator<<(ostream & os, const Point & p) 
{
    os << setprecision(8) << fixed << p.x << ' ' << p.y << endl;
    return os;
}

istream & operator>>(istream & is, Point & p)
{
    is >> p.x >> p.y;
    return is;
}

double cross(const Point & p1, const Point & p2)
{
    return p1.x*p2.y-p1.y*p2.x;
}

bool check_counter_clockwise(const Point & p0, const Point & p1, const Point & p2)
{
    return cross(p1-p0,p2-p0) > 0;
}

bool check_clockwise(const Point & p0, const Point & p1, const Point & p2)
{
    return cross(p1-p0,p2-p0) < 0;
}

double norm(const Point & p)
{
    return sqrt(p*p);
}

bool check_online_back(const Point & p0, const Point & p1, const Point & p2)
{
    Point a(p2-p0), b(p1-p0);
    double norm_a = norm(a), norm_b = norm(b);
    return fabs(a*b+norm_a*norm_b)<ESP && fabs(norm_a)>ESP;
}

bool check_online_front(const Point & p0, const Point & p1, const Point & p2)
{
    Point a(p2-p0), b(p1-p0);
    double norm_a = norm(a), norm_b = norm(b);
    return fabs(a*b-norm_a*norm_b)<ESP && norm_a>norm_b && fabs(norm_a-norm_b)>ESP;
}

bool check_on_segment(const Point & p0, const Point & p1, const Point & p2)
{
    Point a(p2-p0), b(p1-p0);
    double norm_a = norm(a), norm_b = norm(b);
    return fabs(a*b-norm_a*norm_b)<ESP && ((norm_a<norm_b && fabs(norm_a-norm_b)>ESP) || fabs(norm_a-norm_b)<ESP);
}

bool check_parallel(const Line & l1, const Line & l2)
{
    return cross(l1.direction, l2.direction)==0;
}

bool check_orthogonal(const Line & l1, const Line & l2)
{
    return l1.direction*l2.direction==0;
}

bool check_on_segment(const  Segment & s, const Point & p)
{
    return cross(p-s.first_end, p-s.second_end)==0 && max(norm(p-s.first_end), norm(p-s.second_end))-s.length <= ESP;
}

bool check_intersection(const Segment & s1, const Segment & s2)
{
    bool mutually_different_side = 
        check_clockwise(s1.first_end, s1.second_end, s2.first_end) ==
        check_counter_clockwise(s1.first_end, s1.second_end, s2.second_end) &&
        check_clockwise(s2.first_end, s2.second_end, s1.first_end) ==
        check_counter_clockwise(s2.first_end, s2.second_end, s1.second_end) &&
        cross(s1.direction, s2.direction)!=0; //not parallel
        

    bool on_segment = 
        check_on_segment(s1, s2                                                                                                                                                     .first_end) ||
        check_on_segment(s1, s2.second_end) ||
        check_on_segment(s2, s1.first_end) ||
        check_on_segment(s2, s1.second_end);

    return mutually_different_side || on_segment;

}


Point get_cross_point(const Segment & s1, const Segment & s2)
{
    // if (!check_intersection(s1,s2))
    //     return;

    double D = s1.a*s2.b - s2.a*s1.b, D1 = -(s1.c*s2.b-s1.b*s2.c), D2 = -(s1.a*s2.c-s2.a*s1.c);

    return Point(D1/D, D2/D);
}

bool check_online(const Point & p, const Line & l)
{
    return fabs((p-l.point_online)*l.get_normal()) < ESP;
    //alternative: calculate the distance from point to line
    //alternative 2: cross product equals to 0
}

bool check_different_sides(const Point & p1, const Point & p2, const Line & l)
{
    return cross(l.direction, p1-l.point_online)*cross(l.direction, p2-l.point_online) < 0;
}

bool check_intersection(const Segment & s, const Line & l)
{
    return 
        check_online(s.first_end, l) ||
        check_online(s.second_end, l) ||
        check_different_sides(s.first_end, s.second_end, l);

    // return cross(l.direction, s.first_end-l.point_online)*cross(l.direction, s.second_end-l.point_online) <= 0;
}


// bool check_intersection_segments(const Segment & s1, const Segment & s2)
// {
//     return 
// }

double distance_point_to_point(const Point & p1, const Point & p2)
{
    return norm(p1-p2);
}

double distance_PL(const Point & p, const Line & l)
{
    return fabs((p-l.point_online)*l.get_normal())/norm(l.get_normal());
}

double distance_point_to_segment(const Point & p, const Segment & s)
{
    if (check_intersection(s, Line(p, p+s.get_normal())))
        return distance_PL(p, Line(s.first_end, s.second_end));
    return min(distance_point_to_point(p, s.first_end), distance_point_to_point(p, s.second_end));
}

double distance_PS(const Point & p, const Segment & s)
{
    // if (check_intersection(s, Line(p, p+s.get_normal())))
    //     return fabs((p-s.first_end)*s.get_normal())/norm(s.get_normal());
    // return min(distance_point_to_point(p, s.first_end), distance_point_to_point(p, s.second_end));

    if ((s.first_end-s.second_end)*(p-s.second_end) < 0)
        return distance_point_to_point(p, s.second_end);
    if ((s.second_end-s.first_end)*(p-s.first_end) < 0)
        return distance_point_to_point(p, s.first_end);
    return distance_PL(p, Line(s.first_end, s.second_end));
}


double distance_segment_to_segment(const Segment & s1, const Segment & s2)
{
    if (check_intersection(s1, s2))
        return 0;
    double d1 = min(distance_point_to_segment(s1.first_end, s2), distance_point_to_segment(s1.second_end, s2));
    double d2 = min(distance_point_to_segment(s2.first_end, s1), distance_point_to_segment(s2.second_end, s1));
    return min(d1, d2);
}


Measured memory_bytes: 3300