import unittest

import chainer
import numpy

from chainer import testing
from chainer import training
from chainer.training import triggers
from chainer.training import util


class DummyUpdater(training.Updater):

    def __init__(self):
        self.iteration = 0
        self.epoch = 0

    def finalize(self):
        pass

    def get_all_optimizers(self):
        return {}

    def update(self):
        self.iteration += 1
        self.epoch += 1

    def epoch(self):
        return self.epoch

    @property
    def is_new_epoch(self):
        return False

    @property
    def epoch_detail(self):
        return self.epoch


def _test_trigger(self, trigger, key, accuracies, expected):
    updater = DummyUpdater()
    trainer = training.Trainer(updater)
    for accuracy, expected in zip(accuracies, expected):
        updater.update()
        trainer.observation = {key: accuracy}
        self.assertEqual(trigger(trainer), expected)


class TestEarlyStoppingTrigger(unittest.TestCase):

    def test_early_stopping_trigger_with_accuracy(self):
        key = 'main/accuracy'
        trigger = triggers.EarlyStoppingTrigger(monitor=key, patients=3,
                                                check_trigger=(1, 'epoch'),
                                                verbose=False)
        trigger = util.get_trigger(trigger)

        accuracies = [0.5, 0.5, 0.6, 0.7, 0.6, 0.4, 0.3, 0.2]
        accuracies = numpy.asarray([
            chainer.Variable(numpy.asarray(acc, dtype=numpy.float32))
            for acc in accuracies])

        expected = [False, False, False, False, False, False, True, True]
        _test_trigger(self, trigger, key, accuracies, expected)

    def test_early_stopping_trigger_with_loss(self):
        key = 'main/loss'
        trigger = triggers.EarlyStoppingTrigger(monitor=key, patients=3,
                                                check_trigger=(1, 'epoch'))
        trigger = util.get_trigger(trigger)

        accuracies = [100, 80, 30, 10, 20, 24, 30, 35]
        accuracies = numpy.asarray([
            chainer.Variable(numpy.asarray(acc, dtype=numpy.float32))
            for acc in accuracies])

        expected = [False, False, False, False, False, False, True, True]
        _test_trigger(self, trigger, key, accuracies, expected)

    def test_early_stopping_trigger_with_max_epoch(self):
        key = 'main/loss'
        trigger = triggers.EarlyStoppingTrigger(monitor=key, patients=3,
                                                check_trigger=(1, 'epoch'),
                                                max_trigger=(3, 'epoch'))
        trigger = util.get_trigger(trigger)

        accuracies = [100, 80, 30]
        accuracies = numpy.asarray([
            chainer.Variable(numpy.asarray(acc, dtype=numpy.float32))
            for acc in accuracies])

        expected = [False, False, True]
        _test_trigger(self, trigger, key, accuracies, expected)

    def test_early_stopping_trigger_with_max_iteration(self):
        key = 'main/loss'
        trigger = triggers.EarlyStoppingTrigger(monitor=key, patients=3,
                                                check_trigger=(1, 'epoch'),
                                                max_trigger=(3, 'iteration'))
        trigger = util.get_trigger(trigger)

        accuracies = [100, 80, 30]
        accuracies = numpy.asarray([
            chainer.Variable(numpy.asarray(acc, dtype=numpy.float32))
            for acc in accuracies])

        expected = [False, False, True]
        _test_trigger(self, trigger, key, accuracies, expected)


testing.run_module(__name__, __file__)

@@ -71,37 +71,8 @@
 ing%0A
-from chainer import training%0A
 from
@@ -145,599 +145,176 @@
 l%0A%0A%0A
-class DummyUpdater(training.Updater):%0A%0A    def __init__(self):%0A        self.iteration = 0%0A        self.epoch = 0%0A%0A    def finalize(self):%0A        pass%0A%0A    def get_all_optimizers(self):%0A        return %7B%7D%0A%0A    def update(self):%0A        self.iteration += 1%0A        self.epoch += 1%0A%0A    def epoch(self):%0A        return self.epoch%0A%0A    @property%0A    def is_new_epoch(self):%0A        return False%0A%0A    @property%0A    def epoch_detail(self):%0A        return self.epoch%0A%0A%0Adef _test_trigger(self, trigger, key, accuracies, expected):%0A    updater = DummyUpdater()%0A    trainer = training.Trainer(updater)
+def _test_trigger(self, trigger, key, accuracies, expected):%0A    trainer = testing.training.get_trainer_with_mock_updater(%0A        stop_trigger=None, iter_per_epoch=1)%0A
 %0A   
@@ -375,16 +375,24 @@
         
+trainer.
 updater.

Use get_trainer_with_mock_updater