import java.util.*


fun main(args:Array<String>):Unit{
    repeat(readLine()!!.toInt()){
        val (h, w) = readLine()!!.split(' ').map(String::toInt)
        val objectsMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.".associate {
            if (it == '.') Pair(it, NoObject as SuspiciousObject) else Pair(it, Something())
        }
        val state = Array(h){readLine()!!.map{objectsMap[it]!!}.toTypedArray()}
        val objects = objectsMap.map{it.value}
        for (i in 0 until h) for (j in 0 until w) state[i][j].addAppearPoint(Point(i, j))
        for (i in 0 until h) for (j in 0 until w){
            objects.filter{it.isOverlapPosition(Point(i, j))}.forEach {
                state[i][j].addOverlapObjectUnlessSame(it)
                it.addCoverObjectUnlessSame(state[i][j])
            }
        }
        var canBeTop = objects.filter(SuspiciousObject::isCanBeTop)
        var rest = objects.filterNot(SuspiciousObject::isCanBeTop)
        while (canBeTop.isNotEmpty()){
            canBeTop.forEach { it.useAsTop() }
            canBeTop = rest.filter(SuspiciousObject::isCanBeTop)
            rest = rest.filterNot(SuspiciousObject::isCanBeTop)
        }
        println(if (rest.size == 1) "SAFE" else "SUSPICIOUS")
    }
}

data class Point(val x:Int, val y:Int)
interface SuspiciousObject{
    fun addAppearPoint(point:Point):Unit
    fun addOverlapObjectUnlessSame(other:SuspiciousObject):Unit
    fun addCoverObjectUnlessSame(other:SuspiciousObject):Unit
    val isCanBeTop:Boolean
    fun useAsTop():Unit
    fun isOverlapPosition(point:Point):Boolean
}

object NoObject:SuspiciousObject {
    override fun addAppearPoint(point: Point) {}
    override fun addOverlapObjectUnlessSame(other: SuspiciousObject) {}
    override fun addCoverObjectUnlessSame(other: SuspiciousObject) {}
    override val isCanBeTop: Boolean
            get() = false
    override fun useAsTop() {}
    override fun isOverlapPosition(point: Point): Boolean = true
}

class Something:SuspiciousObject {
    private var minX:Int = Int.MAX_VALUE
    private var maxX:Int = Int.MIN_VALUE
    private var minY:Int = Int.MAX_VALUE
    private var maxY:Int = Int.MIN_VALUE
    private val mUnder:Stack<SuspiciousObject> = Stack()
    private var mOverCount:Int = 0
    private val mOver:Stack<SuspiciousObject> = Stack()
    override fun addAppearPoint(point: Point) {
        if (minX > point.x)
            minX = point.x
        if (maxX < point.x)
            maxX = point.x
        if (minY > point.y)
            minY = point.y
        if (maxY < point.y)
            maxY = point.y
    }

    override fun addOverlapObjectUnlessSame(other: SuspiciousObject) {
        if (this == other || mUnder.contains(other)) return
        mUnder.push(other)
    }

    override fun addCoverObjectUnlessSame(other: SuspiciousObject) {
        if (this == other || mOver.contains(other)) return
        mOver.push(other)
        ++mOverCount
    }

    override val isCanBeTop: Boolean
        get() = mOverCount == 0

    override fun useAsTop() {
        mUnder.forEach {
            when(it){
                is Something -> it.mOverCount--
                else ->{}
            }
        }
    }

    override fun isOverlapPosition(point: Point): Boolean {
        return point.x in (minX .. maxX) && point.y in (minY .. maxY)
    }
}


Measured memory_bytes: 173668