summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/prebuild/license/tst_licenses.pl224
1 files changed, 219 insertions, 5 deletions
diff --git a/tests/prebuild/license/tst_licenses.pl b/tests/prebuild/license/tst_licenses.pl
index 1f3dd225..23523e36 100755
--- a/tests/prebuild/license/tst_licenses.pl
+++ b/tests/prebuild/license/tst_licenses.pl
@@ -14,6 +14,8 @@ use Cwd qw( abs_path getcwd );
use List::Util qw( first );
use Pod::Usage;
use Test::More;
+use JSON;
+use Data::Dumper;
=head1 NAME
@@ -530,6 +532,205 @@ sub checkLicense_legacy
return 1;
}
+
+##########################################################################################
+my $licenseRuleFileName = "licenseRule.json";
+# Format of the license rule json file
+# It's an array
+# Each entry in the array corresponds to a set of rules
+# There are sets of rules for files with certain endings.
+# A file ending cannot be present in two "file_pattern_ending".
+# A more constraining ending (like "special.txt") needs to appear in a "file_pattern_ending"
+# located before the "file_pattern_ending" of a less constraining ending (like ".txt").
+# [
+# {
+# "file_pattern_ending" : [ "special.txt", ".end1"],
+# "location" : {
+# "src/" : {# the location (the directory or file) for which the spdx rule applies
+# "comment" : "blabla", # this is optional
+# "file type" : "module", #corresponding file type in terms of quip18
+# "spdx" : ["BDS3"] # the authorized license expression(s)
+# },
+# "src/tools" : { # the location is checked from the base of $QT_MODULE_TO_TEST.
+# "file type" : "tools",
+# "spdx" : ["first_possibility", "second_possibility"]
+# }
+# }
+# },
+# {
+# "file_pattern_ending" : [ ".txt", "end2"],
+# "location" : {
+# "src/a_special_file.txt" : {
+# "comment" : "Exception",
+# "file type" : "module",
+# "spdx" : ["BDS3"]
+# }
+# }
+# },
+# {
+# "location" : {
+# "src" : {
+# "comment" : "blabla",
+# "file type" : "module",
+# "spdx" : ["BDS3"]
+# },
+# "src/tools" : {
+# "file type" : "tools",
+# "spdx" : ["first_possibility", "second_possibility"]
+# }
+# }
+# }
+#]
+# The last entry does NOT have a "file_pattern_ending"
+# It's the set of rules for the files whose ending does not define the license rule.
+# For those files the license rule only depends on the location of the file in
+# the Qt module repository.
+
+my $keyLocation = "location";
+my $keyFileType = "file type";
+my $keySpdxEpr = "spdx";
+my $keyEnding = "file_pattern_ending";
+
+my $licenseRules;
+my @caseLocationList; # for each case, the list of dir and/or files is ordered
+
+my $licenseRuleValid;
+sub readLicenseRules
+{
+ my $filename = "$QT_MODULE_TO_TEST/$licenseRuleFileName";
+ my $message = "";
+ if (open (my $json_str, $filename)) {
+ local $/ = undef;
+ $licenseRules = decode_json <$json_str>;
+ close($json_str);
+ } else {
+ $message = "$QT_MODULE_TO_TEST/$licenseRuleFileName does not exist.";
+ $message .= " The license usage is not tested.\n";
+ return $message;
+ }
+
+ #for debug
+ #print Data::Dumper->Dump([$licenseRules], [qw(licenseRules)]);
+
+ # this is to check that a given ending appears in only one list of endings
+ my @arrayOfEndings = ();
+
+ my @allCases = @$licenseRules;
+ for (my $index = 0; $index < @allCases; $index++) {
+ my $case = $allCases[$index];
+ # ordering the location, to review the deeper one first in checkLicenseUsage
+ @{$caseLocationList[$index]} = (sort { length $b <=> length $a }
+ keys %{%$case{$keyLocation}});
+ if (exists $case->{$keyEnding}) {
+ push(@{$arrayOfEndings[$index]} , @{%$case{$keyEnding}});
+ }
+
+ if (!exists $case->{$keyEnding} and $#allCases > $index) {
+ $message .= "warning: the default case with NO ". $keyEnding
+ ." needs to appear last.\n";
+ }
+ }
+
+ #print Dumper @arrayOfEndings;
+ # Make sure a file ending appears only once
+ # and that the file endings are logically ordered
+ foreach my $arrayIndex (0 .. ($#arrayOfEndings-1)) {
+ foreach my $compArrayIndex ($arrayIndex+1 .. $#arrayOfEndings) {
+ foreach my $end (@{$arrayOfEndings[$arrayIndex]}) {
+ # If a file_pattern_ending entry matches a subsequent file_pattern_ending entry
+ # the file is considered invalid
+ # in other words, the more restrictive ending should appear in a
+ # file_pattern_ending
+ # that is first in the file
+ # The following is invalid
+ # {
+ # "file_pattern_ending" : ["doc"]
+ # ...
+ # },
+ # { "file_pattern_ending" : [".doc"]
+ # ...
+ # }
+ # two equivalent ending cannot appear in two different file_pattern_ending
+ # The following is invalid
+ # {
+ # "file_pattern_ending" : [".doc"]
+ # ...
+ # },
+ # { "file_pattern_ending" : [".doc"]
+ # ...
+ # }
+ # The following is valid
+ # {
+ # "file_pattern_ending" : [".doc"]
+ # ...
+ # },
+ # { "file_pattern_ending" : ["doc"]
+ # ...
+ # }
+ foreach my $compEnd (@{$arrayOfEndings[$compArrayIndex]}) {
+ if ($compEnd eq $end) {
+ $message .= "warning: " . $compEnd
+ . " appears in more than one rule set.\n";
+ last;
+ }
+ if ($compEnd =~ qr{\Q$end\E$}) {
+ $message .= "warning: " . $compEnd
+ . " is more restrictive than " . $end . ".\n";
+ $message .= "The rule set for "
+ . $compEnd . " needs to appear first.\n";
+ }
+ }
+ }
+ }
+ }
+
+ if (length($message)) {
+ $message .= "Please review " . $filename
+ . "\nwarning: The license usage is not tested.\n";
+ }
+ return $message;
+}
+
+sub checkLicenseUsage
+{
+ my $expression = shift;
+ my $shortfilename = shift;
+ my $index = 0;
+ foreach my $case (@$licenseRules) {
+ # Entering the default case, were no $keyEnding exists.
+ # or
+ # Entering a case if the file ending corresponds to one of the ending
+ # in @{%$case{$keyEnding}}.
+ # $keyEnding entries should be string so the regular expression is built using \Q and \E
+ if (!exists $case->{$keyEnding} or
+ first {$shortfilename =~ qr{\Q$_\E$}} @{%$case{$keyEnding}}) {
+ # using the ordered list of location, to check deeper first
+ foreach my $location (@{$caseLocationList[$index]}) {
+ # location can be expressed as regular expression, for this reason no \Q \E here
+ if ($shortfilename =~ qr{^$location}) {
+ # the SPDX expression should be entered in the json file as string,
+ # using \Q \E to convert to regexpr
+ if (!first {$expression eq $_}
+ @{%$case{$keyLocation}->{$location}->{$keySpdxEpr}}) {
+ my $type = %$case{$keyLocation}->{$location}->{$keyFileType};
+ fail("error: $shortfilename is using wrong license SPDX expression \n"
+ . $expression . ". \n" . "Please check the rule for " . $type
+ . " in ".$licenseRuleFileName.".\n");
+ return 0;
+ }
+ return 1;
+ }
+ }
+ }
+ $index++;
+ }
+
+ fail("error: No license rule could be found for $shortfilename Please check "
+ .$licenseRuleFileName.".\n");
+ return 0;
+
+}
+
sub checkSPDXLicenseIdentifier
{
my $expression = shift;
@@ -547,7 +748,14 @@ sub checkSPDXLicenseIdentifier
return 0;
}
}
- return 1;
+
+ # only checking the license usage if a $licenseRuleFileName has been found
+ # in $QT_MODULE_TO_TEST
+ if (!$licenseRuleValid) {
+ return 1;
+ } else {
+ return checkLicenseUsage($expression, $shortfilename);
+ }
}
#
@@ -606,11 +814,9 @@ sub checkLicense_SPDX
fail("error: $shortfilename does not appear to contain a license header");
return;
}
- }
- # Check the license identifiers we've found.
- foreach (@licenseIdentifiers) {
- if (!checkSPDXLicenseIdentifier($_, $shortfilename)) {
+ # Checking only the first SPDX tag found
+ if (!checkSPDXLicenseIdentifier($licenseIdentifiers[0], $shortfilename)) {
return 0;
}
}
@@ -781,6 +987,8 @@ sub run
}
}
+
+
#
# Phase 3: Decide which files we are going to scan.
#
@@ -823,6 +1031,9 @@ sub run
#
# Phase 4: Scan the files
#
+ my $readLicenseRulesMessage = readLicenseRules;
+ $licenseRuleValid = !length($readLicenseRulesMessage);
+
my $numTests = $#filesToScan + 1;
if ($numTests <= 0) {
plan skip_all => "Module $moduleName appears to have no files that must be scanned";
@@ -835,6 +1046,9 @@ sub run
foreach ( @filesToScan ) {
&$checkLicense($_);
}
+ if (!$licenseRuleValid) {
+ print("$readLicenseRulesMessage");
+ }
}
}