from collections import Counter
DIRECTIONS = [(1, 0), (0, 1), (-1, 0), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
def main():
length = int(input())
for _ in range(length):
row, col = list(map(int, input().split(" ")))
graph = []
for _ in range(row):
graph.append(list(input()))
res = solver(graph, row, col)
print("YES" if res else "NO")
def solver(graph, row, col):
cnt = 0
for r in range(row - 1):
for c in range(col - 1):
list = [graph[r][c], graph[r + 1][c], graph[r][c + 1], graph[r + 1][c + 1]]
grids = [(r, c), (r + 1, c), (r, c + 1), (r + 1, c + 1)]
counter = Counter(list)
if counter["*"] == 3:
cnt += 1
if not check(grids, graph):
return False
return sum(s.count('*') for s in graph) == cnt * 3
def check(list, graph):
for x, y in list:
if graph[x][y] != "*":
continue
for del_x, del_y in DIRECTIONS:
_x, _y = x + del_x, y + del_y
if _x < 0 or _x >= len(graph) or _y < 0 or _y >= len(graph[0]):
continue
if (_x, _y) in list:
continue
if graph[_x][_y] == "*":
return False
return True
main()
#include <bits/stdc++.h>
typedef long long int ll;
using namespace std;
#define ULL unsigned long long
#define MOD 1000000007;
#define INF 1e18
#define nline "\n"
#define rep for(int i = 0 ; i < n ; i++)
#define all(x) (x).begin(), (x).end()
#define repin(a,b,c) for(int (a) = (b) ; (a) <= (c) ; (a)++)
#define repde(a,b,c) for(int (a) = (b) ; (a) >= (c) ; (a)--)
#define max(a,b) ((a<b) ? b : a)
#define min(a,b) ((a>b) ? b : a)
#define max3(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
#define min3(a,b,c) (a < b ? (a < c ? a : c) : (b < c ? b : c))
/*-------------------------------------------------------------------------------------*/
ll gcd(ll A,ll B){if(B==0) return A; else return gcd(B, A % B);}
ll expo(ll a, ll b, ll mod) {ll res = 1; while (b > 0) {if (b & 1)res = (res * a) % mod;
a = (a * a) % mod; b = b >> 1;} return res;}
void swap(int &x, int &y) {int temp = x; x = y; y = temp;}
void google(int t){cout << "Case #" << t << ": ";}
bool isPrime(int n){if(n <= 1)return false;if(n <= 3)return true;
if(n%2==0||n%3==0)return false;for(int i=5;i*i<=n;i=i+6)
if(n%i==0||n%(i+2)==0)return false; return true;}
ll mod_add(ll a, ll b, ll m){a=a%m; b=b%m; return(((a+b)%m)+m)%m;}
ll mod_mul(ll a, ll b, ll m){a=a%m; b=b%m; return(((a*b)%m)+m)%m;}
ll mod_sub(ll a, ll b, ll m){a=a%m; b=b%m; return(((a-b)%m)+m)%m;}
int mod_expo(int x,int n,int M){
if(n==0)
return 1;
else if(n%2 == 0)
return mod_expo((x*x)%M,n/2,M);
else
return (x*mod_expo((x*x)%M,(n-1)/2,M))%M;
}
/*-------------------------------------------------------------------------------------*/
#define pb push_back
#define mp make_pair
void solve(){
int n,m;
cin>>n>>m;
vector<string>v;
for(int i = 0 ; i < n ; i++){
string x;
cin>>x;
v.push_back(x);
}
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m-2 ; j++){
if(v[i][j]=='*' && v[i][j+1]=='*' && v[i][j+2]=='*'){
cout<<"NO"<<nline;
return;
}
}
}
for(int i = 0 ; i < n-2 ; i++){
for(int j = 0 ; j < m ; j++){
if(v[i][j]=='*' && v[i+1][j]=='*' && v[i+2][j]=='*'){
cout<<"NO"<<nline;
return;
}
}
}
vector<int>adj[n*m];
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
if(v[i][j]=='*'){
bool ch = true;
if(i+1 < n && v[i+1][j]=='*'){
adj[m*i+j].push_back(m*(i+1)+j);
ch = false;
}
if(j+1 < m && v[i][j+1]=='*'){
adj[m*i+j].push_back(m*i+(j+1));
ch = false;
}
if(i-1 >= 0 && v[i-1][j]=='*'){
adj[m*i+j].push_back(m*(i-1)+j);
ch = false;
}
if(j-1 >= 0 && v[i][j-1]=='*'){
adj[m*i+j].push_back(m*i+(j-1));
ch = false;
}
if(i+1 < n && j+1 < m && v[i+1][j+1]=='*'){
adj[m*i+j].push_back(m*(i+1)+(j+1));
ch = false;
}
if(i+1 < n && j-1 >= 0 && v[i+1][j-1]=='*'){
adj[m*i+j].push_back(m*(i+1)+(j-1));
ch = false;
}
if(i-1 >= 0 && j+1 < m && v[i-1][j+1]=='*'){
adj[m*i+j].push_back(m*(i-1)+(j+1));
ch = false;
}
if(i-1 >= 0 && j >= 0 && v[i-1][j-1]=='*'){
adj[m*i+j].push_back(m*(i-1)+(j-1));
ch = false;
}
if(ch){
cout<<"NO"<<nline;
return;
}
}
}
}
vector<int>vis(n*m,0);
queue<int>q;
int f = 0;
for(int i = 0 ; i < n*m ; i++){
if(vis[i]==0){
f++;
vis[i] = f;
q.push(i);
while(q.size() > 0){
int node = q.front();
q.pop();
for(auto it : adj[node]){
if(vis[it]==0){
vis[it] = f;
q.push(it);
}
}
}
}
}
unordered_map<int,int>mp;
for(auto it : vis){
mp[it]++;
}
for(auto it : mp){
if(it.second > 1 && it.second != 3){
cout<<"NO"<<nline;
return;
}
}
vector<int>adj2[n*m];
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < m ; j++){
if(v[i][j]=='*'){
bool ch2 = true;
if(i+1 < n && v[i+1][j]=='*'){
adj2[m*i+j].push_back(m*(i+1)+j);
ch2 = false;
}
if(j+1 < m && v[i][j+1]=='*'){
adj2[m*i+j].push_back(m*i+(j+1));
ch2 = false;
}
if(i-1 >= 0 && v[i-1][j]=='*'){
adj2[m*i+j].push_back(m*(i-1)+j);
ch2 = false;
}
if(j-1 >= 0 && v[i][j-1]=='*'){
adj2[m*i+j].push_back(m*i+(j-1));
ch2 = false;
}
if(ch2){
cout<<"NO"<<nline;
return;
}
}
}
}
vector<int>vis2(n*m,0);
queue<int>q2;
f = 0;
for(int i = 0 ; i < n*m ; i++){
if(vis2[i]==0){
f++;
vis2[i] = f;
q2.push(i);
while(q2.size() > 0){
int node = q2.front();
q2.pop();
for(auto it : adj[node]){
if(vis2[it]==0){
vis2[it] = f;
q2.push(it);
}
}
}
}
}
unordered_map<int,int>mp2;
for(auto it : vis2){
mp2[it]++;
}
for(auto it : mp2){
if(it.second > 1 && it.second != 3){
cout<<"NO"<<nline;
return;
}
}
cout<<"YES"<<nline;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
#ifdef debug
freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
freopen("log.txt", "w", stderr);
#endif
int t;
cin>>t;
while(t--)
{
solve();
}
#ifdef debug
fprintf(stdout,"\nTIME: %.3lf sec\n", (double)clock()/(CLOCKS_PER_SEC));
#endif
return 0;
}
/* THE END */
1302. Deepest Leaves Sum | 1209. Remove All Adjacent Duplicates in String II |
994. Rotting Oranges | 983. Minimum Cost For Tickets |
973. K Closest Points to Origin | 969. Pancake Sorting |
967. Numbers With Same Consecutive Differences | 957. Prison Cells After N Days |
946. Validate Stack Sequences | 921. Minimum Add to Make Parentheses Valid |
881. Boats to Save People | 497. Random Point in Non-overlapping Rectangles |
528. Random Pick with Weight | 470. Implement Rand10() Using Rand7() |
866. Prime Palindrome | 1516A - Tit for Tat |
622. Design Circular Queue | 814. Binary Tree Pruning |
791. Custom Sort String | 787. Cheapest Flights Within K Stops |
779. K-th Symbol in Grammar | 701. Insert into a Binary Search Tree |
429. N-ary Tree Level Order Traversal | 739. Daily Temperatures |
647. Palindromic Substrings | 583. Delete Operation for Two Strings |
518. Coin Change 2 | 516. Longest Palindromic Subsequence |
468. Validate IP Address | 450. Delete Node in a BST |