import unittest from mock import Mock import os from time import sleep from threading import Thread try: from threading import _Event as Event except ImportError: # The _Event class was renamed to Event in python 3. from threading import Event import serial from mecode.printer import Printer # for python 2/3 compatibility try: reduce except NameError: # In python 3, reduce is no longer imported by default. from functools import reduce try: isinstance("", basestring) def is_str(s): return isinstance(s, basestring) def encode2To3(s): return s def decode2To3(s): return s except NameError: def is_str(s): return isinstance(s, str) def encode2To3(s): return bytes(s, 'UTF-8') def decode2To3(s): return s.decode('UTF-8') HERE = os.path.dirname(os.path.abspath(__file__)) class TestPrinter(unittest.TestCase): def setUp(self): self.p = Printer() self.p.s = Mock(spec=serial.Serial(), name='MockSerial') self.p.s.readline.return_value = encode2To3('ok\n') self.p.s.timeout = 1 self.p.s.writeTimeout = 1 def tearDown(self): self.p.paused = False self.p.disconnect() def test_disconnect(self): #disconnect should work without having called start or connect self.p.disconnect() self.p.start() self.assertTrue(self.p._read_thread.is_alive()) self.p.disconnect() self.assertFalse(self.p._read_thread.is_alive()) self.assertFalse(self.p._print_thread.is_alive()) def test_load_file(self): self.p.load_file(os.path.join(HERE, 'test.gcode')) expected = [] with open(os.path.join(HERE, 'test.gcode')) as f: for line in f: line = line.strip() if ';' in line: # clear out the comments line = line.split(';')[0] if line: expected.append(line) self.assertEqual(self.p._buffer, expected) def test_sendline(self): self.p.start() testline = 'no new line' self.p.sendline(testline) while len(self.p.sentlines) == 0: sleep(0.01) self.p.s.write.assert_called_with(encode2To3('N1 no new line*44\n')) testline = 'with new line\n' self.p.sendline(testline) while len(self.p.sentlines) == 1: sleep(0.01) self.p.s.write.assert_called_with(encode2To3('N2 with new line*44\n')) def test_start(self): self.assertIsNone(self.p._read_thread) self.assertIsNone(self.p._print_thread) self.p.start() self.assertTrue(self.p._read_thread.is_alive()) def test_ok_received(self): self.assertIsInstance(self.p._ok_received, Event) self.assertTrue(self.p._ok_received.is_set()) def test_printing(self): self.assertFalse(self.p.printing) self.p.load_file(os.path.join(HERE, 'test.gcode')) self.p.start() self.assertTrue(self.p.printing) while self.p.printing: sleep(0.1) #print self.p.sentlines[-1] self.assertFalse(self.p.printing) def test_start_print_thread(self): self.assertIsNone(self.p._print_thread) self.assertFalse(self.p.stop_printing) self.p._start_print_thread() self.assertIsInstance(self.p._print_thread, Thread) self.assertFalse(self.p.stop_printing) def test_start_read_thread(self): self.assertIsNone(self.p._read_thread) self.assertFalse(self.p.stop_reading) self.p._start_read_thread() self.assertIsInstance(self.p._read_thread, Thread) self.assertFalse(self.p.stop_reading) self.assertTrue(self.p._read_thread.is_alive()) def test_empty_buffer(self): self.p.load_file(os.path.join(HERE, 'test.gcode')) self.p.start() while self.p.printing: sleep(0.01) self.assertEqual(self.p.s.write.call_count, len(self.p._buffer)) self.assertEqual(self.p._current_line_idx, len(self.p._buffer)) def test_pause(self): self.p.load_file(os.path.join(HERE, 'test.gcode')) self.p.start() self.p.paused = True self.assertTrue(self.p._print_thread.is_alive()) sleep(.1) expected = self.p._current_line_idx sleep(1) self.assertEqual(self.p._current_line_idx, expected) self.p.paused = False while self.p.printing: sleep(0.01) self.assertNotEqual(self.p._current_line_idx, expected) def test_next_line(self): self.p.load_file(os.path.join(HERE, 'test.gcode')) line = self.p._next_line() expected = 'N1 M900*43\n' self.assertEqual(line, expected) self.p._current_line_idx = 1 line = self.p._next_line() expected = 'N2 G90*18\n' self.assertEqual(line, expected) def test_get_response_no_threads_running(self): with self.assertRaises(RuntimeError): self.p.get_response('test') def test_get_response_timeout(self): self.p._is_read_thread_running = lambda: True resp = self.p.get_response('test', timeout=0.2) expected = '' # We expect to get a blank response when the timeout is hit. self.assertEqual(resp, expected) #def test_readline_timeout(self): # def side_effect(): # yield 'ok ' # yield '58404\n' # while True: # yield 'ok\n' # self.p.s.readline.side_effect = side_effect() # with self.assertRaises(RuntimeError): # self.p._start_read_thread() if __name__ == '__main__': unittest.main()