#!/usr/bin/env python

# Slitherlink
# Phil Bordelon

import os
import sys

DEBUG = os.getenv("DEBUG", False)

# Two defines for switching between state during the reading process.
LINK = 1
GRID = 2

# A define for the ? character that means 'dunno.'
UNKNOWN = -1

# A very boring Container class, to make .foo easy to use.
class Container(object):
   pass

def readPuzzle():

   puzzle = Container()
   puzzle.links = []
   puzzle.grid = {}

   # Read in the height and width.
   height, width = [int(x) for x in sys.stdin.readline().strip().split()]

   puzzle.height = height
   puzzle.width = width

   # The representation of a puzzle toggles between lines that consist of
   # links and nodes and lines that consist of links and values.  We will
   # use a very basic state machine that switches between those two
   # states to handle each "type" of input.

   # The first row in the puzzle is links and nodes.
   row_state = LINK

   # Loop through all N*2+1 rows of the grid.
   for i in range(height * 2 + 1):
      line = sys.stdin.readline().strip()

      if row_state == LINK:

         # Use another state machine to go between the 'grid' (the # signs we
         # don't care about) and the links.
         char_state = GRID
         for j in range(width * 2 + 1):
            
            if char_state == GRID:

               # Skip this character; switch to the other state for the next.
               char_state = LINK 

            elif char_state == LINK:

               if line[j] == "-":
                  puzzle.links.append((i, j))

               # Switch back to the 'skip' state for the next character.
               char_state = GRID
         
         # Switch state for the next line to values-and-links.
         row_state = GRID

      elif row_state == GRID:

         # Once again, we need state, so we reuse 'link' and 'grid'.
         char_state = LINK
         for j in range(width * 2 + 1):

            character = line[j]

            if char_state == LINK:
               if character == "|":

                  # Add the link to the list.
                  puzzle.links.append((i, j))

               # Switch to the 'value' state for the next character.
               char_state = GRID

            elif char_state == GRID:

               # It should be one of 0, 1, 2, 3, or ?.  Handle these cases.
               if character.isdigit():

                  if int(character) < 0 or int(character) > 3:
                     sys.exit("ERROR: Invalid number %s in row '%s'!" % (character, line))

                  puzzle.grid[(i, j)] = int(character)
               else:
                  puzzle.grid[(i, j)] = UNKNOWN

               # Switch to the 'link' state for the next character.
               char_state = LINK

         # Switch state for the next line to nodes-and-links.
         row_state = LINK

   return puzzle

def linkListAtSpot(location):

   # The list of possible links at a location.  Although technically
   # you can't go further left or right or up or down than the limits
   # of the board size, because of our representation we can cheat and
   # not special-case those values, as they won't show up in the link
   # list.  I like lazy.  (Of course, I spent lots of space here /explaining/
   # it ...)  Interestingly, this actually works for both nodes and
   # number squares, due to the way that the board is laid out:
   #
   #  |                       -
   # -#-  is equivalent to   |?| ... from a certain point of view.
   #  |                       -

   loc_x, loc_y = location

   return [(loc_x - 1, loc_y), (loc_x + 1, loc_y),
           (loc_x, loc_y - 1), (loc_x, loc_y + 1)]

def nodeListAtLink(link):

   # If the link is vertical, it will have an even Y component; if it is
   # horizontal, it will have an even X component.  We use that information
   # to determine where the nodes that connect to a particular link are.

   link_x, link_y = link
   if link_x % 2 == 0:
      return [(link_x, link_y - 1), (link_x, link_y + 1)]
   else:
      return [(link_x - 1, link_y), (link_x + 1, link_y)]

def oneAndOnlyOneLoop(puzzle):

   # As the name implies, this function verifies that there is one and only
   # one complete loop in the puzzle.

   # First, the easiest test: All valid loops have at least four segments.
   if len(puzzle.links) < 4:
      return False

   # Get a copy of the list of all links, as we're going to be removing
   # elements from it as we make sure there's only one loop.
   link_list = puzzle.links[:]

   # Pick an arbitrary link; remove it from the list.
   curr_link = link_list[0]
   link_list.remove(curr_link)

   # Find both of its ends.  With the link removed from the list, our
   # goal is to return to the other end having consumed every link.  Think
   # of the loop as a (hopefully) continuous chain; we're removing one link
   # and nosing our way down the chain in the hopes that we return to the
   # "other side" of the removed link.

   curr_node, final_node = nodeListAtLink(curr_link)

   # Put this link in the list of used links.
   used_links = [curr_link]

   # Now, time to loop through all the links, marking them off as we encounter
   # them.
   done = False
   while not done:

      # Find all unused links at the current node.
      potential_links_here = linkListAtSpot(curr_node)
      links_here = [x for x in link_list if x in potential_links_here]
      
      # There had damn well only be one, otherwise there are too many
      # links at this node (as we've already tossed away the /other/ link
      # that got us here).
      if len(links_here) != 1:
         return False

      # Okay, we've got a link to use.  Pull it from the link_list ...
      link_list.remove(links_here[0])

      # ... and move to the node at the other end.  We abuse the nodeListAtLink
      # function; I used to have a custom one that did fancy if/then stuff to
      # get the other end of a node-plus-link combo, but this is easier.
      # Please forgive the rather scary abuse of a list comprehension to do so.
      curr_node = [x for x in nodeListAtLink(links_here[0]) if x != curr_node][0]

      # If we're at the final_node, we can quit.  There may be extra links
      # here (which is an invalid puzzle), but we'll check that outside the
      # loop.
      if curr_node == final_node:
         done = True

   # Okay, we've made a loop in the puzzle.  If there are /any/ segments left,
   # the puzzle is invalid.  Otherwise, it's got one and only one loop.
   if len(link_list) > 0:
      return False

   return True

def checkNumbers(puzzle):

   # This function makes sure that any non-UNKNOWN ("?") number in the puzzle
   # has the proper number of links around it.

   # Loop through the size of the puzzle.  Note that the values are at
   # odd-valued locations on the grid, assuming indices that start at 0:
   #
   #    01234
   #    #-#-# 0
   #    |?|?| 1
   #    #-#-# 2
   #    |?|?| 3
   #    #-#-# 4
   #    
   for i in range(puzzle.height):
      for j in range(puzzle.width):

         # Convert the loop numbers to actual grid-number locations.
         num_x = i * 2 + 1
         num_y = j * 2 + 1

         # We only care about this location if it's not UNKNOWN.
         number = puzzle.grid[(num_x, num_y)]
         if number != UNKNOWN:

            # Get the list of links surrounding this spot.
            potential_links = linkListAtSpot((num_x, num_y))
            links = [x for x in puzzle.links if x in potential_links]

            # If the number doesn't equal the number of links, it's invalid.
            if len(links) != number:
               return False

   # We checked all the numbers, and they were all valid.
   return True

if "__main__" == __name__:

   dataset_count = int(sys.stdin.readline())
   for dataset_loop in range(dataset_count):

      # Read the puzzle in.
      puzzle = readPuzzle()

      # First, check for a one-and-only-one loop ...
      one_loop = oneAndOnlyOneLoop(puzzle)
      if not one_loop:
         print "INVALID"
      else:

         # Drat, we actually have to check the numbers.
         valid_numbers = checkNumbers(puzzle)

         if not valid_numbers:
            print "INVALID"
         else:
            
            # Passed both tests.
            print "VALID"