def test_contrib(self): config = LintConfig() contrib_rules = ["contrib-title-conventional-commits", "CC1"] config.set_general_option("contrib", ",".join(contrib_rules)) self.assertEqual(config.contrib, contrib_rules) # Check contrib-title-conventional-commits contrib rule actual_rule = config.rules.find_rule( "contrib-title-conventional-commits") self.assertTrue(actual_rule.is_contrib) self.assertEqual(ustr(type(actual_rule)), "<class 'conventional_commit.ConventionalCommit'>") self.assertEqual(actual_rule.id, 'CT1') self.assertEqual(actual_rule.name, u'contrib-title-conventional-commits') self.assertEqual(actual_rule.target, rules.CommitMessageTitle) expected_rule_option = options.ListOption( "types", [ "fix", "feat", "chore", "docs", "style", "refactor", "perf", "test", "revert" ], "Comma separated list of allowed commit types.", ) self.assertListEqual(actual_rule.options_spec, [expected_rule_option]) self.assertDictEqual(actual_rule.options, {'types': expected_rule_option}) # Check contrib-body-requires-signed-off-by contrib rule actual_rule = config.rules.find_rule( "contrib-body-requires-signed-off-by") self.assertTrue(actual_rule.is_contrib) self.assertEqual(ustr(type(actual_rule)), "<class 'signedoff_by.SignedOffBy'>") self.assertEqual(actual_rule.id, 'CC1') self.assertEqual(actual_rule.name, u'contrib-body-requires-signed-off-by') # reset value (this is a different code path) config.set_general_option("contrib", "contrib-body-requires-signed-off-by") self.assertEqual( actual_rule, config.rules.find_rule("contrib-body-requires-signed-off-by")) self.assertIsNone( config.rules.find_rule("contrib-title-conventional-commits")) # empty value config.set_general_option("contrib", "") self.assertListEqual(config.contrib, [])
def test_set_general_option_negative(self): config = LintConfig() # Note that we shouldn't test whether we can set unicode because python just doesn't allow unicode attributes with self.assertRaisesRegex(LintConfigError, "'foo' is not a valid gitlint option"): config.set_general_option("foo", u"bår") # try setting _config_path, this is a real attribute of LintConfig, but the code should prevent it from # being set with self.assertRaisesRegex(LintConfigError, "'_config_path' is not a valid gitlint option"): config.set_general_option("_config_path", u"bår") # invalid verbosity` incorrect_values = [-1, u"föo"] for value in incorrect_values: expected_msg = ustr(r"Option 'verbosity' must be a positive integer \(current value: '{0}'\)").format(value) with self.assertRaisesRegex(LintConfigError, expected_msg): config.verbosity = value incorrect_values = [4] for value in incorrect_values: with self.assertRaisesRegex(LintConfigError, "Option 'verbosity' must be set between 0 and 3"): config.verbosity = value # invalid ignore_xxx_commits ignore_attributes = ["ignore_merge_commits", "ignore_fixup_commits", "ignore_squash_commits", "ignore_revert_commits"] incorrect_values = [-1, 4, u"föo"] for attribute in ignore_attributes: for value in incorrect_values: option_name = attribute.replace("_", "-") with self.assertRaisesRegex(LintConfigError, "Option '{0}' must be either 'true' or 'false'".format(option_name)): setattr(config, attribute, value) # invalid ignore -> not here because ignore is a ListOption which converts everything to a string before # splitting which means it it will accept just about everything # invalid debug with self.assertRaisesRegex(LintConfigError, "Option 'debug' must be either 'true' or 'false'"): config.debug = u"föobar" # extra-path has its own negative test # invalid target with self.assertRaisesRegex(LintConfigError, ustr(r"Option target must be an existing directory \(current value: 'föo/bar'\)")): config.target = u"föo/bar"
def test_extra_path_negative(self): config = LintConfig() regex = ustr(r"Option extra-path must be either an existing directory or file \(current value: 'föo/bar'\)") # incorrect extra_path with self.assertRaisesRegex(LintConfigError, regex): config.extra_path = u"föo/bar" # extra path contains classes with errors with self.assertRaisesRegex(LintConfigError, "User-defined rule class 'MyUserLineRule' must have a 'validate' method"): config.extra_path = self.get_sample_path("user_rules/incorrect_linerule")
def test_contrib_negative(self): config = LintConfig() # non-existent contrib rule with self.assertRaisesRegex(LintConfigError, u"No contrib rule with id or name 'föo' found."): config.contrib = u"contrib-title-conventional-commits,föo" # UserRuleError, RuleOptionError should be re-raised as LintConfigErrors side_effects = [rules.UserRuleError(u"üser-rule"), options.RuleOptionError(u"rüle-option")] for side_effect in side_effects: with patch('gitlint.config.rule_finder.find_rule_classes', side_effect=side_effect): with self.assertRaisesRegex(LintConfigError, ustr(side_effect)): config.contrib = u"contrib-title-conventional-commits"
def test_int_option(self): # normal behavior option = IntOption("test-name", 123, "Test Description") self.assertEqual(option.value, 123) self.assertEqual(option.name, "test-name") self.assertEqual(option.description, "Test Description") # re-set value option.set(456) self.assertEqual(option.value, 456) # error on negative int when not allowed expected_error = ustr( r"Option 'test-name' must be a positive integer \(current value: '-123'\)" ) with self.assertRaisesRegex(RuleOptionError, expected_error): option.set(-123) # error on non-int value expected_error = ustr( r"Option 'test-name' must be a positive integer \(current value: 'foo'\)" ) with self.assertRaisesRegex(RuleOptionError, expected_error): option.set("foo") # no error on negative value when allowed and negative int is passed option = IntOption("test-name", 123, "Test Description", allow_negative=True) option.set(-456) self.assertEqual(option.value, -456) # error on non-int value when negative int is allowed expected_error = ustr( r"Option 'test-name' must be an integer \(current value: 'foo'\)") with self.assertRaisesRegex(RuleOptionError, expected_error): option.set("foo")
def test_set_from_config_file_negative(self): config_builder = LintConfigBuilder() # bad config file load foo_path = self.get_sample_path(u"föo") expected_error_msg = u"Invalid file path: {0}".format( re.escape(foo_path)) with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.set_from_config_file(foo_path) # error during file parsing path = self.get_sample_path("config/no-sections") expected_error_msg = u"File contains no section headers." with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.set_from_config_file(path) # non-existing rule path = self.get_sample_path("config/nonexisting-rule") config_builder = LintConfigBuilder() config_builder.set_from_config_file(path) expected_error_msg = u"No such rule 'föobar'" with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.build() # non-existing general option path = self.get_sample_path("config/nonexisting-general-option") config_builder = LintConfigBuilder() config_builder.set_from_config_file(path) expected_error_msg = u"'foo' is not a valid gitlint option" with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.build() # non-existing option path = self.get_sample_path("config/nonexisting-option") config_builder = LintConfigBuilder() config_builder.set_from_config_file(path) expected_error_msg = u"Rule 'title-max-length' has no option 'föobar'" with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.build() # invalid option value path = self.get_sample_path("config/invalid-option-value") config_builder = LintConfigBuilder() config_builder.set_from_config_file(path) expected_error_msg = u"'föo' is not a valid value for option 'title-max-length.line-length'. " + \ ustr(r"Option 'line-length' must be a positive integer \(current value: 'föo'\).") with self.assertRaisesRegex(LintConfigError, expected_error_msg): config_builder.build()
def test_set_rule_option_negative(self): config = LintConfig() # non-existing rule expected_error_msg = u"No such rule 'föobar'" with self.assertRaisesRegex(LintConfigError, expected_error_msg): config.set_rule_option(u'föobar', u'lïne-length', 60) # non-existing option expected_error_msg = u"Rule 'title-max-length' has no option 'föobar'" with self.assertRaisesRegex(LintConfigError, expected_error_msg): config.set_rule_option('title-max-length', u'föobar', 60) # invalid option value expected_error_msg = u"'föo' is not a valid value for option 'title-max-length.line-length'. " + \ ustr(r"Option 'line-length' must be a positive integer \(current value: 'föo'\).") with self.assertRaisesRegex(LintConfigError, expected_error_msg): config.set_rule_option('title-max-length', 'line-length', u"föo")
def test_extra_path(self): config = LintConfig() config.set_general_option("extra-path", self.get_user_rules_path()) self.assertEqual(config.extra_path, self.get_user_rules_path()) actual_rule = config.rules.find_rule('UC1') self.assertTrue(actual_rule.is_user_defined) self.assertEqual(ustr(type(actual_rule)), "<class 'my_commit_rules.MyUserCommitRule'>") self.assertEqual(actual_rule.id, 'UC1') self.assertEqual(actual_rule.name, u'my-üser-commit-rule') self.assertEqual(actual_rule.target, None) expected_rule_option = options.IntOption('violation-count', 1, u"Number of violåtions to return") self.assertListEqual(actual_rule.options_spec, [expected_rule_option]) self.assertDictEqual(actual_rule.options, {'violation-count': expected_rule_option}) # reset value (this is a different code path) config.set_general_option("extra-path", self.SAMPLES_DIR) self.assertEqual(config.extra_path, self.SAMPLES_DIR) self.assertIsNone(config.rules.find_rule("UC1"))
def test_path_option(self): option = PathOption("test-directory", ".", u"Test Description", type=u"dir") self.assertEqual(option.value, os.getcwd()) self.assertEqual(option.name, "test-directory") self.assertEqual(option.description, u"Test Description") self.assertEqual(option.type, u"dir") # re-set value option.set(self.SAMPLES_DIR) self.assertEqual(option.value, self.SAMPLES_DIR) # set to int expected = ustr( r"Option test-directory must be an existing directory \(current value: '1234'\)" ) with self.assertRaisesRegex(RuleOptionError, expected): option.set(1234) # set to non-existing directory non_existing_path = os.path.join(u"/föo", u"bar") expected = ustr( r"Option test-directory must be an existing directory \(current value: '{0}'\)" ) with self.assertRaisesRegex(RuleOptionError, expected.format(non_existing_path)): option.set(non_existing_path) # set to a file, should raise exception since option.type = dir sample_path = self.get_sample_path( os.path.join("commit_message", "sample1")) expected = ustr( r"Option test-directory must be an existing directory \(current value: '{0}'\)" ).format(re.escape(sample_path)) with self.assertRaisesRegex(RuleOptionError, expected): option.set(sample_path) # set option.type = file, file should now be accepted, directories not option.type = u"file" option.set(sample_path) self.assertEqual(option.value, sample_path) expected = ustr( r"Option test-directory must be an existing file \(current value: '{0}'\)" ).format(re.escape(self.get_sample_path())) with self.assertRaisesRegex(RuleOptionError, expected): option.set(self.get_sample_path()) # set option.type = both, files and directories should now be accepted option.type = u"both" option.set(sample_path) self.assertEqual(option.value, sample_path) option.set(self.get_sample_path()) self.assertEqual(option.value, self.get_sample_path()) # Expect exception if path type is invalid option.type = u'föo' expected = ustr( r"Option test-directory type must be one of: 'file', 'dir', 'both' \(current: 'föo'\)" ) with self.assertRaisesRegex(RuleOptionError, expected): option.set("haha")