
This lays the groundwork for interactive init, as well as being able to specify control and compute nodes. Added preliminary config lists for control and compute nodes. Added appropriate default snapctl config settings in install script. Also changed "binary" questions to "boolean" questions, as that's better wording, and it means that my docstrings are not a confusing mix of "boolean" and "binary" when I forget which term I used. Snuck in a fix for the "basic" testing environment -- it was missing the Python requirements, and was therefore failing! Change-Id: I7f95ab68f924fa4d4280703c372b807cc7c77758
133 lines
3.2 KiB
Python
133 lines
3.2 KiB
Python
import sys
|
|
import os
|
|
import unittest
|
|
|
|
import mock
|
|
|
|
# TODO: drop in test runner and get rid of this line.
|
|
sys.path.append(os.getcwd()) # noqa
|
|
|
|
from init.question import (Question, InvalidQuestion, InvalidAnswer,
|
|
AnswerNotImplemented)
|
|
|
|
|
|
##############################################################################
|
|
#
|
|
# Test Fixtures
|
|
#
|
|
##############################################################################
|
|
|
|
|
|
class InvalidTypeQuestion(Question):
|
|
_type = 'foo'
|
|
|
|
|
|
class GoodAutoQuestion(Question):
|
|
_type = 'auto'
|
|
|
|
def yes(self, answer):
|
|
return 'I am a good question!'
|
|
|
|
|
|
class GoodBooleanQuestion(Question):
|
|
_type = 'boolean'
|
|
|
|
def yes(self, answer):
|
|
return True
|
|
|
|
def no(self, answer):
|
|
return False
|
|
|
|
|
|
class GoodStringQuestion(Question):
|
|
"""Pass a string through to the output of Question.ask.
|
|
|
|
# TODO right now, we have separate handlers for Truthy and Falsey
|
|
answers, and this test class basically makes them do the same
|
|
thing. Is this a good pattern?
|
|
|
|
"""
|
|
_type = 'string'
|
|
|
|
def yes(self, answer):
|
|
return answer
|
|
|
|
def no(self, answer):
|
|
return answer
|
|
|
|
|
|
##############################################################################
|
|
#
|
|
# Tests Proper
|
|
#
|
|
##############################################################################
|
|
|
|
|
|
class TestQuestionClass(unittest.TestCase):
|
|
"""
|
|
Test basic features of the Question class.
|
|
|
|
"""
|
|
def test_invalid_type(self):
|
|
|
|
with self.assertRaises(InvalidQuestion):
|
|
InvalidTypeQuestion().ask()
|
|
|
|
def test_valid_type(self):
|
|
|
|
self.assertTrue(GoodBooleanQuestion())
|
|
|
|
@mock.patch('init.question.shell.check_output')
|
|
@mock.patch('init.question.shell.check')
|
|
def test_auto_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = ''
|
|
|
|
self.assertEqual(GoodAutoQuestion().ask(), True)
|
|
|
|
|
|
class TestInput(unittest.TestCase):
|
|
"""
|
|
Test input handling.
|
|
|
|
Takes advantage of the fact that we can override the Question
|
|
class's input handler.
|
|
|
|
"""
|
|
@mock.patch('init.question.shell.check_output')
|
|
@mock.patch('init.question.shell.check')
|
|
def test_boolean_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = 'true'
|
|
|
|
q = GoodBooleanQuestion()
|
|
|
|
for answer in ['yes', 'Yes', 'y']:
|
|
q._input_func = lambda x: answer
|
|
self.assertTrue(q.ask())
|
|
|
|
for answer in ['No', 'n', 'no']:
|
|
q._input_func = lambda x: answer
|
|
self.assertFalse(q.ask())
|
|
|
|
with self.assertRaises(InvalidAnswer):
|
|
q._input_func = lambda x: 'foo'
|
|
q.ask()
|
|
|
|
@mock.patch('init.question.shell.check_output')
|
|
@mock.patch('init.question.shell.check')
|
|
def test_string_question(self, mock_check, mock_check_output):
|
|
mock_check_output.return_value = 'somedefault'
|
|
|
|
q = GoodStringQuestion()
|
|
|
|
for answer in ['foo', 'bar', 'baz', 'yadayadayada']:
|
|
q._input_func = lambda x: answer
|
|
self.assertEqual(answer, q.ask())
|
|
|
|
# Verify that a blank answer defaults properly
|
|
q._input_func = lambda x: ''
|
|
self.assertEqual('somedefault', q.ask())
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|