#include <bits/stdc++.h>

using namespace std;

const int MOD = 1e9 + 7;
const int N = 2010;

struct queue_max
{
	deque<int> q;
	deque<int> w;
	int sum;
	int mx;

	queue_max()
	{
		sum = 0;
		mx = 0;
		q.clear();
		w.clear();
	}

	inline void init()
	{
		sum = 0;
		mx = 0;
		q.clear();
		w.clear();
	}

	inline void add(int x, int ww)
	{
		while (!q.empty() && q.back() < x)
		{
			q.pop_back();
			w.pop_back();
		}
		if (q.empty())
		{
			q.push_back(x);
			w.push_back(ww);
			mx = x;
			sum = ww;
			return;
		}
		q.push_back(x);
		w.push_back(ww);
		if (x < mx) return;
		sum += ww;
		if (sum >= MOD) sum -= MOD;
	}

	inline void del(int x, int ww)
	{
		if (q.front() != x) return;
		q.pop_front();
		w.pop_front();
		if (q.empty()) return;
		if (q.front() == mx)
		{
			sum -= ww;
			if (sum < 0) sum += MOD;
			return;
		}
		mx = q.front();
		sum = 0;
		for (int i = 0; i < (int)q.size(); i++)
		{
			if (q[i] != mx) break;
			sum += w[i];
			if (sum >= MOD) sum -= MOD;
		}
	}
};

int par[N][N], rg[N][N], mx[N][N];

inline void init(int n, int m)
{
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			par[i][j] = j, rg[i][j] = 0, mx[i][j] = j + 1;	
}

inline int find_set(int i, int j)
{
	if (par[i][j] == j) return j;
	return (par[i][j] = find_set(i, par[i][j]));
}

inline void merge_set(int i, int x1, int x2)
{
	x1 = find_set(i, x1);
	x2 = find_set(i, x2);
	if (x1 == x2) return;
	if (rg[i][x1] > rg[i][x2]) swap(x1, x2);
	mx[i][x2] = max(mx[i][x2], mx[i][x1]);
	par[i][x1] = x2;
	if (rg[i][x1] == rg[i][x2]) rg[i][x2]++;
}

inline int gett(int i, int j)
{
	return mx[i][find_set(i, j)];
}

queue_max vx[N], vy[N];
int n, m, q, l[N][N], u[N][N], dp[N][N], kol[N][N];
vector<tuple<int, int, int> > a[N], b[N];

inline void solve()
{
	cin >> n >> m >> q;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			l[i][j] = -1, u[i][j] = -1;
	for (int i = 0; i < m; i++)
		a[i].clear();
	for (int i = 0; i < n; i++)
		b[i].clear();
	for (int i = 0; i < q; i++)
	{
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		x1--, x2--, y1--, y2--;
		if (x1 == x2 || y1 == y2) continue;
		x1++, y1++;
		a[y1].push_back(make_tuple(x1, x2, y2));
		b[x1].push_back(make_tuple(y1, y2, x2));
	}                
	init(m, n);                       
	for (int j = 0; j < m; j++)
		for (tuple<int, int, int> t : a[j])
		{
			int to = get<2>(t);
			int s = get<0>(t);
			int f = get<1>(t);
			for (int x = to; x >= j; x--)
			{
				if (l[s][x] != -1 && gett(x, s) > f) break;
				int p = s;
				while (p <= f)
				{
					if (l[p][x] == -1) 
					{
						l[p][x] = (j - 1);
						if (p > 0 && l[p - 1][x] != -1) merge_set(x, p - 1, p);
						if (p < n - 1 && l[p + 1][x] != -1) merge_set(x, p, p + 1); 
					}
					p = gett(x, p);
				}			
			}
		}                              
	init(n, m);
	for (int i = 0; i < n; i++)
		for (tuple<int, int, int> t : b[i])
		{
			int to = get<2>(t);
			int s = get<0>(t);
			int f = get<1>(t);
			for (int x = to; x >= i; x--)
			{
				if (u[x][s] != -1 && gett(x, s) > f) break;
				int p = s;
				while (p <= f)
				{
					if (u[x][p] == -1) 
					{
						u[x][p] = (i - 1);
						if (p > 0 && u[x][p - 1] != -1) merge_set(x, p - 1, p);
						if (p < m - 1 && u[x][p + 1] != -1) merge_set(x, p, p + 1); 
					}
					p = gett(x, p);
				}			
			}
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
		{
			if (l[i][j] == -1) l[i][j] = j;
			if (u[i][j] == -1) u[i][j] = i;
		}
	for (int i = 0; i < n; i++)
		vx[i].init();
	for (int i = 0; i < m; i++)
		vy[i].init();      
	for (int s = 0; s <= (n + m - 2); s++)
		for (int i = 0; i < min(s + 1, n); i++)
		{
			int j = (s - i);
			if (j < 0 || j >= m) continue;
			dp[i][j] = 1;
			kol[i][j] = 1;
			if (i == 0 || j == 0) continue;
			vx[i].add(dp[i - 1][j - 1], kol[i - 1][j - 1]);
			for (int x = l[i][j - 1]; x < l[i][j]; x++)
				vx[i].del(dp[i - 1][x], kol[i - 1][x]);
			if (l[i][j] < j)
			{
				if (dp[i][j] < vx[i].mx + 1)
				{
					dp[i][j] = vx[i].mx + 1;
					kol[i][j] = 0;
				}
				if (dp[i][j] == vx[i].mx + 1)
				{
					kol[i][j] += vx[i].sum;
					if (kol[i][j] >= MOD) kol[i][j] -= MOD;
				}
			}
			vy[j].add(dp[i - 1][j - 1], kol[i - 1][j - 1]);
			for (int x = u[i - 1][j]; x < u[i][j]; x++)
				vy[j].del(dp[x][j - 1], kol[x][j - 1]);
			if (u[i][j] < i)
			{
				if (dp[i][j] < vy[j].mx + 1)
				{
					dp[i][j] = vy[j].mx + 1;
					kol[i][j] = 0;
				}
				if (dp[i][j] == vy[j].mx + 1)
				{
					kol[i][j] += vy[j].sum;
					if (kol[i][j] >= MOD) kol[i][j] -= MOD;
				}
			}
			if (l[i][j] < j && u[i][j] < i && dp[i][j] == dp[i - 1][j - 1] + 1)
			{
				kol[i][j] -= kol[i - 1][j - 1];
				if (kol[i][j] < 0) kol[i][j] += MOD;
			}
		}                               
	int mx = 0;
	int ans = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
 			mx = max(mx, dp[i][j]);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			if (mx == dp[i][j])   
			{
				ans += kol[i][j];
				if (ans >= MOD) ans -= MOD;
			}
	cout << mx << " " << ans << "\n";					
}

int main()
{
	ios::sync_with_stdio(0);
	int T;
	cin >> T;
	for (int z = 0; z < T; z++)
		solve();
	return 0;
}