From 2665cc33f04f6f128c05c7c3879be2a9a0c81a5b Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Thu, 3 Mar 2016 20:26:51 +0000 Subject: [PATCH 1/7] Add test for triggers in aliases Ensures aliases do not contain any of the triggers defined in categories. --- t/CheatSheets/CheatSheetsJSON.t | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index 9de4f2adb..54aabd828 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -116,9 +116,27 @@ foreach my $path (glob("$json_dir/*.json")){ if (first { lc $_ eq $defaultName } @aliases) { push(@tests, {msg => "aliases should not contain the cheat sheet name ($defaultName)", critical => 1}); } + # Make sure aliases don't contain any category triggers. + while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { + while (my ($trigger_type, $triggers) = each %{$trigger_types}) { + my @triggers = @$triggers; + foreach my $alias (@aliases) { + my $trigger; + if ( + ($trigger_type =~ /^start/ + && ($trigger = first { $alias =~ /^$_/ } @triggers)) + || ($trigger_type =~ /end$/ + && ($trigger = first { $alias =~ /$_$/ } @triggers)) + || ($trigger_type eq 'any' + && ($trigger = first { $alias =~ /$_/ } @triggers)) + ) { + push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => 1}); + } + } + } + } } - ### Sections tests ### $temp_pass = (my $order = $json->{section_order})? 1 : 0; push(@tests, {msg => 'has section_order', critical => 1, pass => $temp_pass}); From 29a2b62aed1408e1343aeca8edae86aee70ddb28 Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Thu, 3 Mar 2016 20:29:21 +0000 Subject: [PATCH 2/7] Remove aliases containing triggers --- share/goodie/cheat_sheets/json/duckduckgo-syntax.json | 3 --- share/goodie/cheat_sheets/json/sql.json | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/share/goodie/cheat_sheets/json/duckduckgo-syntax.json b/share/goodie/cheat_sheets/json/duckduckgo-syntax.json index be3b10eb1..ff7f47544 100644 --- a/share/goodie/cheat_sheets/json/duckduckgo-syntax.json +++ b/share/goodie/cheat_sheets/json/duckduckgo-syntax.json @@ -7,9 +7,6 @@ "sourceName": "Duck.co", "sourceUrl": "https://duck.co/help/results/syntax" }, - "aliases": [ - "ddg syntax","duck duck go syntax" - ], "section_order": [ "Triggers", "Go directly to other sites", diff --git a/share/goodie/cheat_sheets/json/sql.json b/share/goodie/cheat_sheets/json/sql.json index 4eebe65e6..7cec14ea4 100644 --- a/share/goodie/cheat_sheets/json/sql.json +++ b/share/goodie/cheat_sheets/json/sql.json @@ -15,9 +15,8 @@ "SQL Constraints", "Scalar Functions" ], - "aliases":[ - "sql statements", - "sql commands" + "aliases":[ + "sql statements" ], "sections":{ "Data Definition Language (DDL)":[ From 8f8d49b5b202b98e9a56f154e42616eee757e9cb Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Thu, 3 Mar 2016 20:41:44 +0000 Subject: [PATCH 3/7] Add test for aliases against custom triggers Make sure aliases don't contain custom triggers defined in 'triggers.yaml'. --- t/CheatSheets/CheatSheetsJSON.t | 50 ++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index 54aabd828..c7a64193e 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -37,6 +37,28 @@ sub id_to_file_name { return $id . '.json'; } +sub check_aliases_for_triggers { + my ($aliases, $trigger_types) = @_; + my @aliases = @$aliases; + while (my ($trigger_type, $triggers) = each %{$trigger_types}) { + my @triggers = @$triggers; + foreach my $alias (@aliases) { + my $trigger; + if ( + ($trigger_type =~ /^start/ + && ($trigger = first { $alias =~ /^$_/ } @triggers)) + || ($trigger_type =~ /end$/ + && ($trigger = first { $alias =~ /$_$/ } @triggers)) + || ($trigger_type eq 'any' + && ($trigger = first { $alias =~ /$_/ } @triggers)) + ) { + return ($alias, $trigger); + } + } + } + return; +} + # Iterate over all Cheat Sheet JSON files... foreach my $path (glob("$json_dir/*.json")){ next if $ARGV[0] && $path ne "$json_dir/$ARGV[0].json"; @@ -63,8 +85,9 @@ foreach my $path (glob("$json_dir/*.json")){ $temp_pass = (!exists $json->{description} && !$json->{description})? 0 : 1; push(@tests, {msg => "has description (optional but suggested)", critical => 0, pass => $temp_pass}); + my $cheat_id; ### ID tests ### - if (my $cheat_id = $json->{id}) { + if ($cheat_id = $json->{id}) { $temp_pass = id_to_file_name($cheat_id) eq $file_name; push(@tests, {msg => "Invalid file name ($file_name) for ID ($cheat_id)", critical => 1, pass => $temp_pass}); } @@ -77,7 +100,7 @@ foreach my $path (glob("$json_dir/*.json")){ push(@tests, {msg => "Invalid template_type '$template_type'", critical => 1, pass => $temp_pass}); ### Trigger tests ### - if (my $cheat_id = $json->{id}) { + if ($cheat_id) { if (my $custom = $triggers_yaml->{custom_triggers}->{$cheat_id}) { # Duplicate triggers foreach my $trigger (flat_triggers($custom)) { @@ -118,21 +141,14 @@ foreach my $path (glob("$json_dir/*.json")){ } # Make sure aliases don't contain any category triggers. while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { - while (my ($trigger_type, $triggers) = each %{$trigger_types}) { - my @triggers = @$triggers; - foreach my $alias (@aliases) { - my $trigger; - if ( - ($trigger_type =~ /^start/ - && ($trigger = first { $alias =~ /^$_/ } @triggers)) - || ($trigger_type =~ /end$/ - && ($trigger = first { $alias =~ /$_$/ } @triggers)) - || ($trigger_type eq 'any' - && ($trigger = first { $alias =~ /$_/ } @triggers)) - ) { - push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => 1}); - } - } + if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $trigger_types)) { + push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => 1}); + } + } + # Make sure aliases don't contain any custom triggers for the cheat sheet. + if (my $custom = $triggers_yaml->{custom_triggers}{$cheat_id}) { + if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $custom)) { + push(@tests, {msg => "alias ($alias) contains a custom trigger ($trigger)", critical => 1}); } } } From a48799557543e20e58a6bc3101ab41885c5311e8 Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Fri, 4 Mar 2016 19:04:48 +0000 Subject: [PATCH 4/7] Whitelist 'duckduckgo-syntax' for category tests I think this is the best option as it is the only case. --- share/goodie/cheat_sheets/json/duckduckgo-syntax.json | 3 +++ t/CheatSheets/CheatSheetsJSON.t | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/share/goodie/cheat_sheets/json/duckduckgo-syntax.json b/share/goodie/cheat_sheets/json/duckduckgo-syntax.json index ff7f47544..be3b10eb1 100644 --- a/share/goodie/cheat_sheets/json/duckduckgo-syntax.json +++ b/share/goodie/cheat_sheets/json/duckduckgo-syntax.json @@ -7,6 +7,9 @@ "sourceName": "Duck.co", "sourceUrl": "https://duck.co/help/results/syntax" }, + "aliases": [ + "ddg syntax","duck duck go syntax" + ], "section_order": [ "Triggers", "Go directly to other sites", diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index c7a64193e..485663fec 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -22,6 +22,10 @@ my %triggers; my $template_map = $triggers_yaml->{template_map}; +my %category_test_whitelist = ( + duckduckgo_syntax_cheat_sheet => 1, +); + sub flat_triggers { my $data = shift; if (my $triggers = $data->{triggers}) { @@ -141,6 +145,7 @@ foreach my $path (glob("$json_dir/*.json")){ } # Make sure aliases don't contain any category triggers. while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { + last if $category_test_whitelist{$cheat_id}; if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $trigger_types)) { push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => 1}); } From 7b9c57d4b626a919de065da4d0698b9b7a75ba79 Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Fri, 4 Mar 2016 19:52:57 +0000 Subject: [PATCH 5/7] Remove 'any' trigger test --- share/goodie/cheat_sheets/triggers.yaml | 3 +++ t/CheatSheets/CheatSheetsJSON.t | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/share/goodie/cheat_sheets/triggers.yaml b/share/goodie/cheat_sheets/triggers.yaml index 6bfafc293..a73099a4d 100644 --- a/share/goodie/cheat_sheets/triggers.yaml +++ b/share/goodie/cheat_sheets/triggers.yaml @@ -23,6 +23,9 @@ # # Where "trigger_type" is one of start, end, startend, or any. # +# NOTE: The use of 'any' is highly discouraged as it is unstable and +# may not perform as expected. +# # NOTE: Categories should be in alphabetical (lexical) order (and preferably the # triggers and trigger types as well) - this ensures it is as easy as possible # to find relevant categories. diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index 485663fec..58e175b47 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -53,8 +53,6 @@ sub check_aliases_for_triggers { && ($trigger = first { $alias =~ /^$_/ } @triggers)) || ($trigger_type =~ /end$/ && ($trigger = first { $alias =~ /$_$/ } @triggers)) - || ($trigger_type eq 'any' - && ($trigger = first { $alias =~ /$_/ } @triggers)) ) { return ($alias, $trigger); } From d8ff7c9ec407dd153738345c2a80f9f7c841fc7d Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Fri, 4 Mar 2016 20:56:54 +0000 Subject: [PATCH 6/7] Only warn if category not assigned to cheat sheet For the alias-trigger tests. --- share/goodie/cheat_sheets/json/sql.json | 3 ++- t/CheatSheets/CheatSheetsJSON.t | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/share/goodie/cheat_sheets/json/sql.json b/share/goodie/cheat_sheets/json/sql.json index 7cec14ea4..86974da90 100644 --- a/share/goodie/cheat_sheets/json/sql.json +++ b/share/goodie/cheat_sheets/json/sql.json @@ -16,7 +16,8 @@ "Scalar Functions" ], "aliases":[ - "sql statements" + "sql statements", + "sql commands" ], "sections":{ "Data Definition Language (DDL)":[ diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index 58e175b47..0e7adfabe 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -22,10 +22,6 @@ my %triggers; my $template_map = $triggers_yaml->{template_map}; -my %category_test_whitelist = ( - duckduckgo_syntax_cheat_sheet => 1, -); - sub flat_triggers { my $data = shift; if (my $triggers = $data->{triggers}) { @@ -101,21 +97,25 @@ foreach my $path (glob("$json_dir/*.json")){ $temp_pass = (exists $template_map->{$template_type}); push(@tests, {msg => "Invalid template_type '$template_type'", critical => 1, pass => $temp_pass}); + my %categories; + ### Trigger tests ### if ($cheat_id) { if (my $custom = $triggers_yaml->{custom_triggers}->{$cheat_id}) { + %categories = map { $_ => 1 } @{$custom->{additional_categories}}; # Duplicate triggers foreach my $trigger (flat_triggers($custom)) { $temp_pass = $triggers{$trigger}++ ? 0 : 1; push(@tests, {msg => "trigger '$trigger' already in use", critical => 1, pass => $temp_pass}); } # Re-adding category - foreach my $category (@{$custom->{additional_categories}}) { + foreach my $category (keys %categories) { $temp_pass = none { $_ eq $category } @{$template_map->{$template_type}}; push(@tests, {msg => "Category '$category' already assigned", critical => 1, pass => $temp_pass}); } } } + %categories = (%categories, map { $_ => 1 } @{$template_map->{$template_type}}); ### Metadata tests ### my $has_meta = exists $json->{metadata}; @@ -143,9 +143,9 @@ foreach my $path (glob("$json_dir/*.json")){ } # Make sure aliases don't contain any category triggers. while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { - last if $category_test_whitelist{$cheat_id}; + my $critical = $categories{$category}; if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $trigger_types)) { - push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => 1}); + push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => $critical}); } } # Make sure aliases don't contain any custom triggers for the cheat sheet. From c59aece0e12d901a9cf70d3e6a976c4bd47c4d8e Mon Sep 17 00:00:00 2001 From: Ben Moon Date: Mon, 7 Mar 2016 17:26:03 +0000 Subject: [PATCH 7/7] Combine tests that rely on ID being present --- t/CheatSheets/CheatSheetsJSON.t | 64 ++++++++++++++++----------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/t/CheatSheets/CheatSheetsJSON.t b/t/CheatSheets/CheatSheetsJSON.t index 0e7adfabe..c190f32a4 100755 --- a/t/CheatSheets/CheatSheetsJSON.t +++ b/t/CheatSheets/CheatSheetsJSON.t @@ -83,13 +83,6 @@ foreach my $path (glob("$json_dir/*.json")){ $temp_pass = (!exists $json->{description} && !$json->{description})? 0 : 1; push(@tests, {msg => "has description (optional but suggested)", critical => 0, pass => $temp_pass}); - my $cheat_id; - ### ID tests ### - if ($cheat_id = $json->{id}) { - $temp_pass = id_to_file_name($cheat_id) eq $file_name; - push(@tests, {msg => "Invalid file name ($file_name) for ID ($cheat_id)", critical => 1, pass => $temp_pass}); - } - ### Template Type tests ### $temp_pass = (exists $json->{template_type} && $json->{template_type})? 1 : 0; push(@tests, {msg => 'must specify a template type', critical => 1, pass => $temp_pass}); @@ -99,8 +92,12 @@ foreach my $path (glob("$json_dir/*.json")){ my %categories; - ### Trigger tests ### - if ($cheat_id) { + if (my $cheat_id = $json->{id}) { + ### ID tests ### + $temp_pass = id_to_file_name($cheat_id) eq $file_name; + push(@tests, {msg => "Invalid file name ($file_name) for ID ($cheat_id)", critical => 1, pass => $temp_pass}); + + ### Trigger tests ### if (my $custom = $triggers_yaml->{custom_triggers}->{$cheat_id}) { %categories = map { $_ => 1 } @{$custom->{additional_categories}}; # Duplicate triggers @@ -114,7 +111,32 @@ foreach my $path (glob("$json_dir/*.json")){ push(@tests, {msg => "Category '$category' already assigned", critical => 1, pass => $temp_pass}); } } + + ### Alias tests ### + if (my $aliases = $json->{aliases}) { + my @aliases = @{$aliases}; + if ("@aliases" =~ /[[:upper:]]/) { + push(@tests, {msg => "uppercase detected in alias - aliases should be lowercase", critical => 1}); + } + if (first { lc $_ eq $defaultName } @aliases) { + push(@tests, {msg => "aliases should not contain the cheat sheet name ($defaultName)", critical => 1}); + } + # Make sure aliases don't contain any category triggers. + while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { + my $critical = $categories{$category}; + if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $trigger_types)) { + push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => $critical}); + } + } + # Make sure aliases don't contain any custom triggers for the cheat sheet. + if (my $custom = $triggers_yaml->{custom_triggers}{$cheat_id}) { + if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $custom)) { + push(@tests, {msg => "alias ($alias) contains a custom trigger ($trigger)", critical => 1}); + } + } + } } + %categories = (%categories, map { $_ => 1 } @{$template_map->{$template_type}}); ### Metadata tests ### @@ -132,30 +154,6 @@ foreach my $path (glob("$json_dir/*.json")){ $temp_pass = (my $url = $json->{metadata}{sourceUrl})? 1 : 0; push(@tests, {msg => "sourceUrl is not undef $name", critical => 1, pass => $temp_pass, skip => 1});; - ### Alias tests ### - if (my $aliases = $json->{aliases}) { - my @aliases = @{$aliases}; - if ("@aliases" =~ /[[:upper:]]/) { - push(@tests, {msg => "uppercase detected in alias - aliases should be lowercase", critical => 1}); - } - if (first { lc $_ eq $defaultName } @aliases) { - push(@tests, {msg => "aliases should not contain the cheat sheet name ($defaultName)", critical => 1}); - } - # Make sure aliases don't contain any category triggers. - while (my ($category, $trigger_types) = each %{$triggers_yaml->{categories}}) { - my $critical = $categories{$category}; - if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $trigger_types)) { - push(@tests, {msg => "alias ($alias) contains a trigger ($trigger) defined in the '$category' category", critical => $critical}); - } - } - # Make sure aliases don't contain any custom triggers for the cheat sheet. - if (my $custom = $triggers_yaml->{custom_triggers}{$cheat_id}) { - if (my ($alias, $trigger) = check_aliases_for_triggers(\@aliases, $custom)) { - push(@tests, {msg => "alias ($alias) contains a custom trigger ($trigger)", critical => 1}); - } - } - } - ### Sections tests ### $temp_pass = (my $order = $json->{section_order})? 1 : 0; push(@tests, {msg => 'has section_order', critical => 1, pass => $temp_pass});