#include <cmath>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <ostream>
#include <vector>

const double kEpsilon = 1e-10;
inline bool equals(double a, double b)
{
    return fabs(a - b) < kEpsilon;
}

class Point
{
  public:
    double x, y;

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

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

    double SquaredNorm()
    {
        return x * x + y * y;
    }
    double abs()
    {
        return sqrt(this->SquaredNorm());
    }

    bool operator<(const Point &p) const
    {
        return x != p.x ? x < p.x : y < p.y;
    }
    bool operator==(const Point &p) const
    {
        return fabs(x - p.x) < kEpsilon && fabs(y - p.y) < kEpsilon;
    }

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

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

using Vector = Point;

struct Segment
{
    Point p1, p2;

    Segment() = default;
    Segment(Point p1, Point p2) : p1(p1), p2(p2)
    {
    }
};

struct Line
{
    Point p1, p2;

    Line() = default;
    Line(Point &p1, Point &p2) : p1(p1), p2(p2)
    {
    }
    Line(Segment &s) : p1(s.p1), p2(s.p2)
    {
    }
};

int ccw(Point &p0, Point &p1, Point &p2)
{
    auto a = p1 - p0;
    auto b = p2 - p0;

    auto cross_z = a.cross(b);

    if (cross_z > 0.0)
        return 1;
    else if (cross_z < 0.0)
        return -1;
    else
    {
        auto dot_prod = a.dot(b);
        if (dot_prod < 0.0)
            return 100;
        else if (b.abs() > a.abs())
            return -100;
        else
        {
            return 0;
        }
    }
}

bool intersection(Segment &s1, Segment &s2)
{
    return ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0.0 &&
           ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0.0;
}

double distance(Point &a, Point &b)
{
    return (a - b).abs();
}

double distance(Point &p, Line &l)
{
    auto q = l.p1 - l.p2;
    auto r = p - l.p2;
    return fabs(r.cross(q)) / q.abs();
}

double distance(Point &p, Segment &s)
{
    auto q1 = s.p2 - s.p1;
    auto q2 = p - s.p1;
    auto r1 = s.p1 - s.p2;
    auto r2 = p - s.p2;
    if (q1.dot(q2) >= 0.0 && r1.dot(r2) >= 0.0)
    {
        Line l(s);
        return distance(p, l);
    }
    else
    {
        return std::min(distance(p, s.p1), distance(p, s.p2));
    }
}

double distance(Segment &s1, Segment &s2)
{
    if (intersection(s1, s2))
        return 0.0;
    return std::min(std::min(distance(s1.p1, s2), distance(s1.p2, s2)),
                    std::min(distance(s2.p1, s1), distance(s2.p2, s1)));
}

int main()
{
    Segment s1, s2;
    int q;
    std::cin >> q;

    for (size_t i = 0; i < q; ++i)
    {
        std::cin >> s1.p1.x >> s1.p1.y;
        std::cin >> s1.p2.x >> s1.p2.y;
        std::cin >> s2.p1.x >> s2.p1.y;
        std::cin >> s2.p2.x >> s2.p2.y;

        std::cout << std::setprecision(20);
        std::cout << distance(s1, s2) << std::endl;
    }
}



Measured memory_bytes: 3288