def testCLAClassificationRecord(self):
        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "Vector",
            "anomalyLabel": "Label"
        }

        state = _CLAClassificationRecord(**record)
        self.assertEqual(state.ROWID, record['ROWID'])
        self.assertEqual(state.anomalyScore, record['anomalyScore'])
        self.assertEqual(state.anomalyVector, record['anomalyVector'])
        self.assertEqual(state.anomalyLabel, record['anomalyLabel'])
        self.assertEqual(state.setByUser, False)

        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "Vector",
            "anomalyLabel": "Label",
            "setByUser": True
        }

        state = _CLAClassificationRecord(**record)
        self.assertEqual(state.ROWID, record['ROWID'])
        self.assertEqual(state.anomalyScore, record['anomalyScore'])
        self.assertEqual(state.anomalyVector, record['anomalyVector'])
        self.assertEqual(state.anomalyLabel, record['anomalyLabel'])
        self.assertEqual(state.setByUser, record['setByUser'])
  def testCLAClassificationRecord(self):
    record = {
      "ROWID": 0,
      "anomalyScore": 1.0,
      "anomalyVector": "Vector",
      "anomalyLabel": "Label"
    }

    state = _CLAClassificationRecord(**record)
    self.assertEqual(state.ROWID, record['ROWID'])
    self.assertEqual(state.anomalyScore, record['anomalyScore'])
    self.assertEqual(state.anomalyVector, record['anomalyVector'])
    self.assertEqual(state.anomalyLabel, record['anomalyLabel'])
    self.assertEqual(state.setByUser, False)

    record = {
      "ROWID": 0,
      "anomalyScore": 1.0,
      "anomalyVector": "Vector",
      "anomalyLabel": "Label",
      "setByUser": True
    }

    state = _CLAClassificationRecord(**record)
    self.assertEqual(state.ROWID, record['ROWID'])
    self.assertEqual(state.anomalyScore, record['anomalyScore'])
    self.assertEqual(state.anomalyVector, record['anomalyVector'])
    self.assertEqual(state.anomalyLabel, record['anomalyLabel'])
    self.assertEqual(state.setByUser, record['setByUser'])
    def testSetGetWaitRecords(self, classifyState):
        self.helper._recordsCache = [
            Mock(ROWID=10, anomalyLabel=["Test"], setByUser=False),
            Mock(ROWID=11, anomalyLabel=["Test"], setByUser=False),
            Mock(ROWID=12, anomalyLabel=["Test"], setByUser=True)
        ]

        self.helper.setParameter('trainRecords', None, 20)

        self.assertEqual(self.helper.trainRecords, 20)
        self.assertEqual(len(classifyState.mock_calls),
                         len(self.helper._recordsCache))

        self.assertEqual(self.helper.getParameter('trainRecords'), 20)

        # Test invalid parameter type
        self.assertRaises(Exception, self.helper.setParameter, 'trainRecords',
                          None, 'invalid')

        # Test invalid value before first record ROWID in cache
        state = {
            "ROWID": 1000,
            "anomalyScore": 1.0,
            "anomalyVector": [1, 4, 5],
            "anomalyLabel": "Label"
        }
        record = _CLAClassificationRecord(**state)
        self.helper._recordsCache = [state]
        self.assertRaises(Exception, self.helper.setParameter, 'trainRecords',
                          None, 0)
    def testAddRecordToKNN(self, getAnomalyVector):
        getAnomalyVector.return_value = numpy.array([0, 1, 0, 0, 1, 0, 1, 1])
        values = {'categoryRecencyList': [1, 2, 3]}
        classifier = self.helper._knnclassifier
        classifier.getParameter = Mock(side_effect=values.get)
        classifier._knn.learn = Mock()
        classifier._knn.prototypeSetCategory = Mock()
        state = {
            "ROWID": 5,
            "anomalyScore": 1.0,
            "anomalyVector": numpy.array([1, 5, 7, 8]),
            "anomalyLabel": ["Label"],
            "setByUser": False
        }
        record = _CLAClassificationRecord(**state)

        # Test with record not already in KNN
        self.helper._addRecordToKNN(record)
        classifier._knn.learn.assert_called_once_with(
            getAnomalyVector.return_value, ANY, rowID=state['ROWID'])
        self.assertTrue(not classifier._knn.prototypeSetCategory.called)
        classifier._knn.learn.reset_mock()

        # Test with record already in KNN
        values = {'categoryRecencyList': [1, 2, 3, 5]}
        classifier.getParameter.side_effect = values.get
        self.helper._addRecordToKNN(record)
        classifier._knn.prototypeSetCategory.assert_called_once_with(
            state['ROWID'], ANY)
        self.assertTrue(not classifier._knn.learn.called)
    def testRecomputeRecordFromKNN(self, getAnomalyVector):
        getAnomalyVector.return_value = "Vector"
        self.helper.trainRecords = 0
        values = {
            "categoryRecencyList": [1, 2, 3, 5, 6, 7, 8, 9],
            "latestDists": numpy.array([0.7, 0.2, 0.5, 1, 0.3, 0.2, 0.1]),
            "categories": ["A", "B", "C", "D", "E", "F", "G"],
        }
        classifier = self.helper._knnclassifier
        classifier.getLatestDistances = Mock(return_value=values["latestDists"])
        classifier.getCategoryList = Mock(return_value=values["categories"])
        classifier.getParameter = Mock(side_effect=values.get)
        classifier.setParameter = Mock()
        classifier.compute = Mock()
        state = {"ROWID": 5, "anomalyScore": 1.0, "anomalyVector": "", "anomalyLabel": ["Label"], "setByUser": False}
        record = _CLAClassificationRecord(**state)

        # Test finding best category before record - exists
        self.helper._classificationMaxDist = 0.4
        self.helper._autoDetectWaitRecords = 0
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, "B")

        # Test finding best category before record - does not exists
        self.helper._classificationMaxDist = 0.1
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, None)

        # Test finding best category before record - not record before
        record.ROWID = 0
        self.helper._classificationMaxDist = 0.1
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, None)
    def testAddRecordToKNN(self, getAnomalyVector):
        getAnomalyVector.return_value = numpy.array([0, 1, 0, 0, 1, 0, 1, 1])
        values = {"categoryRecencyList": [1, 2, 3]}
        classifier = self.helper._knnclassifier
        classifier.getParameter = Mock(side_effect=values.get)
        classifier._knn.learn = Mock()
        classifier._knn.prototypeSetCategory = Mock()
        state = {
            "ROWID": 5,
            "anomalyScore": 1.0,
            "anomalyVector": numpy.array([1, 5, 7, 8]),
            "anomalyLabel": ["Label"],
            "setByUser": False,
        }
        record = _CLAClassificationRecord(**state)

        # Test with record not already in KNN
        self.helper._addRecordToKNN(record)
        classifier._knn.learn.assert_called_once_with(getAnomalyVector.return_value, ANY, rowID=state["ROWID"])
        self.assertTrue(not classifier._knn.prototypeSetCategory.called)
        classifier._knn.learn.reset_mock()

        # Test with record already in KNN
        values = {"categoryRecencyList": [1, 2, 3, 5]}
        classifier.getParameter.side_effect = values.get
        self.helper._addRecordToKNN(record)
        classifier._knn.prototypeSetCategory.assert_called_once_with(state["ROWID"], ANY)
        self.assertTrue(not classifier._knn.learn.called)
  def testSetGetWaitRecords(self, classifyState):
    self.helper._recordsCache = [
      Mock(ROWID=10, anomalyLabel=["Test"], setByUser=False),
      Mock(ROWID=11, anomalyLabel=["Test"], setByUser=False),
      Mock(ROWID=12, anomalyLabel=["Test"], setByUser=True)]
    
    self.helper.setParameter('trainRecords', None, 20)
    
    self.assertEqual(self.helper.trainRecords, 20)
    self.assertEqual(len(classifyState.mock_calls),
        len(self.helper._recordsCache))

    self.assertEqual(self.helper.getParameter('trainRecords'), 20)

    # Test invalid parameter type
    self.assertRaises(Exception, self.helper.setParameter,
      'trainRecords', None, 'invalid')

    # Test invalid value before first record ROWID in cache
    state = {
      "ROWID": 1000,
      "anomalyScore": 1.0,
      "anomalyVector": [1,4,5],
      "anomalyLabel": "Label"
    }
    record = _CLAClassificationRecord(**state)
    self.helper._recordsCache = [state]
    self.assertRaises(Exception, self.helper.setParameter,
      'trainRecords', None, 0)
    def testGetAnomalyVector(self):
        state = {"ROWID": 0, "anomalyScore": 1.0, "anomalyVector": [1, 4, 5], "anomalyLabel": "Label"}
        record = _CLAClassificationRecord(**state)
        self.helper._anomalyVectorLength = 10
        vector = self.helper._getStateAnomalyVector(record)

        self.assertEqual(len(vector), self.helper._anomalyVectorLength)
        self.assertEqual(vector.nonzero()[0].tolist(), record.anomalyVector)
 def testCompute(self, constructRecord, getParam, classifyState):
     params = {"trainRecords": 0}
     getParam.side_effect = params.get
     state = {"ROWID": 0, "anomalyScore": 1.0, "anomalyVector": [1, 4, 5], "anomalyLabel": "Label"}
     record = _CLAClassificationRecord(**state)
     constructRecord.return_value = record
     self.helper.compute(dict(), dict())
     classifyState.assert_called_once_with(record)
     self.assertEqual(self.helper.labelResults, state["anomalyLabel"])
    def testCLAClassificationRecordGetState(self):
        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "Vector",
            "anomalyLabel": "Label",
            "setByUser": False,
        }

        state = _CLAClassificationRecord(**record)

        self.assertEqual(state.__getstate__(), record)
    def testCLAClassificationRecordGetState(self):
        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "Vector",
            "anomalyLabel": "Label",
            "setByUser": False
        }

        state = _CLAClassificationRecord(**record)

        self.assertEqual(state.__getstate__(), record)
    def testGetAnomalyVector(self):
        state = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": [1, 4, 5],
            "anomalyLabel": "Label"
        }
        record = _CLAClassificationRecord(**state)
        self.helper._anomalyVectorLength = 10
        vector = self.helper._getStateAnomalyVector(record)

        self.assertEqual(len(vector), self.helper._anomalyVectorLength)
        self.assertEqual(vector.nonzero()[0].tolist(), record.anomalyVector)
 def testCompute(self, constructRecord, getParam, classifyState):
     params = {'trainRecords': 0}
     getParam.side_effect = params.get
     state = {
         "ROWID": 0,
         "anomalyScore": 1.0,
         "anomalyVector": [1, 4, 5],
         "anomalyLabel": "Label"
     }
     record = _CLAClassificationRecord(**state)
     constructRecord.return_value = record
     self.helper.compute(dict(), dict())
     classifyState.assert_called_once_with(record)
     self.assertEqual(self.helper.labelResults, state['anomalyLabel'])
    def testCompute(self, createRecord, updateState):
        state = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": numpy.array([1, 0, 0, 0, 1]),
            "anomalyLabel": "Label"
        }
        record = _CLAClassificationRecord(**state)
        createRecord.return_value = record

        inputs = dict()
        outputs = dict()

        # Test add first record
        self.helper.cacheSize = 10
        self.helper.trainRecords = 0
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        updateState.assert_called_once_with(self.helper._recordsCache[-1])

        # Test add record before wait records
        updateState.reset_mock()
        self.helper.cacheSize = 10
        self.helper.trainRecords = 10
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 2)
        self.assertTrue(not updateState.called)

        # Test exceeded cache length
        updateState.reset_mock()
        self.helper.cacheSize = 1
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.assertTrue(not updateState.called)
    def testCompute(self, createRecord, updateState):
        state = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": numpy.array([1, 0, 0, 0, 1]),
            "anomalyLabel": "Label",
        }
        record = _CLAClassificationRecord(**state)
        createRecord.return_value = record

        inputs = dict()
        outputs = dict()

        # Test add first record
        self.helper.cacheSize = 10
        self.helper.trainRecords = 0
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        updateState.assert_called_once_with(self.helper._recordsCache[-1])

        # Test add record before wait records
        updateState.reset_mock()
        self.helper.cacheSize = 10
        self.helper.trainRecords = 10
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 2)
        self.assertTrue(not updateState.called)

        # Test exceeded cache length
        updateState.reset_mock()
        self.helper.cacheSize = 1
        self.helper._recordsCache = []
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.helper.compute(inputs, outputs)
        self.assertEqual(self.helper._recordsCache[-1], record)
        self.assertEqual(len(self.helper._recordsCache), 1)
        self.assertTrue(not updateState.called)
    def testCLAClassificationRecordSetState(self):
        record = {"ROWID": None, "anomalyScore": None, "anomalyVector": None, "anomalyLabel": None, "setByUser": None}

        state = _CLAClassificationRecord(**record)

        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "Vector",
            "anomalyLabel": "Label",
            "setByUser": False,
        }

        state.__setstate__(record)

        self.assertEqual(state.ROWID, record["ROWID"])
        self.assertEqual(state.anomalyScore, record["anomalyScore"])
        self.assertEqual(state.anomalyVector, record["anomalyVector"])
        self.assertEqual(state.anomalyLabel, record["anomalyLabel"])
        self.assertEqual(state.setByUser, record["setByUser"])
    def testRecomputeRecordFromKNN(self, getAnomalyVector):
        getAnomalyVector.return_value = "Vector"
        self.helper.trainRecords = 0
        values = {
            'categoryRecencyList': [1, 2, 3, 5, 6, 7, 8, 9],
            'latestDists': numpy.array([0.7, 0.2, 0.5, 1, 0.3, 0.2, 0.1]),
            'categories': ['A', 'B', 'C', 'D', 'E', 'F', 'G']
        }
        classifier = self.helper._knnclassifier
        classifier.getLatestDistances = Mock(
            return_value=values['latestDists'])
        classifier.getCategoryList = Mock(return_value=values['categories'])
        classifier.getParameter = Mock(side_effect=values.get)
        classifier.setParameter = Mock()
        classifier.compute = Mock()
        state = {
            "ROWID": 5,
            "anomalyScore": 1.0,
            "anomalyVector": "",
            "anomalyLabel": ["Label"],
            "setByUser": False
        }
        record = _CLAClassificationRecord(**state)

        # Test finding best category before record - exists
        self.helper._classificationMaxDist = 0.4
        self.helper._autoDetectWaitRecords = 0
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, 'B')

        # Test finding best category before record - does not exists
        self.helper._classificationMaxDist = 0.1
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, None)

        # Test finding best category before record - not record before
        record.ROWID = 0
        self.helper._classificationMaxDist = 0.1
        result = self.helper._recomputeRecordFromKNN(record)
        self.assertEqual(result, None)
    def testUpdateState(self, toLabelList, recompute, deleteRecord, addRecord):
        record = {"ROWID": 0, "anomalyScore": 1.0, "anomalyVector": "", "anomalyLabel": ["Label"], "setByUser": False}

        # Test record not labeled and not above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 0
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [])
        deleteRecord.assert_called_once_with([state])

        # Test record not labeled and above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 0.5
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)

        self.assertEqual(state.anomalyLabel, [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL])
        addRecord.assert_called_once_with(state)

        # Test record not labeled and above threshold during wait period
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 10
        self.helper.anomalyThreshold = 0.5
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)

        self.assertEqual(state.anomalyLabel, [])
        self.assertTrue(not addRecord.called)

        # Test record labeled and not above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 0
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = ["Label"]
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, ["Label"])
        self.assertTrue(not addRecord.called)

        # Test setByUser
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = ["Label 2"]
        recordCopy = copy.deepcopy(record)
        recordCopy["setByUser"] = True
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [recordCopy["anomalyLabel"][0], toLabelList.return_value[0]])
        addRecord.assert_called_once_with(state)

        # Test removal of above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = []
        recordCopy = copy.deepcopy(record)
        recordCopy["setByUser"] = True
        recordCopy["anomalyLabel"] = [
            KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL,
            KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + KNNAnomalyClassifierRegion.AUTO_TAG,
        ]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [])

        # Auto classified threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        recordCopy = copy.deepcopy(record)
        recordCopy["setByUser"] = True
        recordCopy["anomalyLabel"] = [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(
            state.anomalyLabel,
            [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + KNNAnomalyClassifierRegion.AUTO_TAG],
        )
        addRecord.assert_called_once_with(state)

        # Test precedence of threshold label above auto threshold label
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 0.8
        toLabelList.return_value = [
            KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL,
            KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + KNNAnomalyClassifierRegion.AUTO_TAG,
        ]
        recordCopy = copy.deepcopy(record)
        recordCopy["setByUser"] = True
        recordCopy["anomalyLabel"] = [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL])
        addRecord.assert_called_once_with(state)
    def testUpdateState(self, toLabelList, recompute, deleteRecord, addRecord):
        record = {
            "ROWID": 0,
            "anomalyScore": 1.0,
            "anomalyVector": "",
            "anomalyLabel": ["Label"],
            "setByUser": False
        }

        # Test record not labeled and not above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 0
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [])
        deleteRecord.assert_called_once_with([state])

        # Test record not labeled and above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 0.5
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)

        self.assertEqual(state.anomalyLabel, \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL])
        addRecord.assert_called_once_with(state)

        # Test record not labeled and above threshold during wait period
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 10
        self.helper.anomalyThreshold = 0.5
        toLabelList.return_value = []
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)

        self.assertEqual(state.anomalyLabel, [])
        self.assertTrue(not addRecord.called)

        # Test record labeled and not above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.trainRecords = 0
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = ["Label"]
        state = _CLAClassificationRecord(**record)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, ["Label"])
        self.assertTrue(not addRecord.called)

        # Test setByUser
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = ["Label 2"]
        recordCopy = copy.deepcopy(record)
        recordCopy['setByUser'] = True
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(
            state.anomalyLabel,
            [recordCopy["anomalyLabel"][0], toLabelList.return_value[0]])
        addRecord.assert_called_once_with(state)

        # Test removal of above threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = []
        recordCopy = copy.deepcopy(record)
        recordCopy['setByUser'] = True
        recordCopy['anomalyLabel'] = \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL,
           KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + \
            KNNAnomalyClassifierRegion.AUTO_TAG]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel, [])

        # Auto classified threshold
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 1.1
        toLabelList.return_value = \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        recordCopy = copy.deepcopy(record)
        recordCopy['setByUser'] = True
        recordCopy['anomalyLabel'] = \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(state.anomalyLabel,
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + \
            KNNAnomalyClassifierRegion.AUTO_TAG])
        addRecord.assert_called_once_with(state)

        # Test precedence of threshold label above auto threshold label
        deleteRecord.reset_mock()
        addRecord.reset_mock()
        self.helper.anomalyThreshold = 0.8
        toLabelList.return_value = \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL,
            KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL + \
            KNNAnomalyClassifierRegion.AUTO_TAG]
        recordCopy = copy.deepcopy(record)
        recordCopy['setByUser'] = True
        recordCopy['anomalyLabel'] = \
          [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL]
        state = _CLAClassificationRecord(**recordCopy)
        self.helper.classifyState(state)
        self.assertEqual(
            state.anomalyLabel,
            [KNNAnomalyClassifierRegion.AUTO_THRESHOLD_CLASSIFIED_LABEL])
        addRecord.assert_called_once_with(state)