FOSSology  4.7.1
Open Source License Compliance by Open Source Software
test_scanners.cc
1 /*
2  SPDX-FileCopyrightText: © 2014-15, 2018 Siemens AG
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
6 
7 #include <cppunit/TestFixture.h>
8 #include <cppunit/extensions/HelperMacros.h>
9 
10 #include "regex.hpp"
11 #include "regscan.hpp"
12 #include "copyrightUtils.hpp"
13 #include "cleanEntries.hpp"
14 #include <list>
15 #include <cstring>
16 #include <ostream>
17 
18 using namespace std;
19 
25 ostream& operator<<(ostream& out, const list<match>& l)
26 {
27  for (auto m = l.begin(); m != l.end(); ++m)
28  out << '[' << m->start << ':' << m->end << ':' << m->type << ']';
29  return out;
30 }
31 
35 const char testContent[] = "© 2007 Hugh Jackman\n\n"
36  "Copyright 2004 my company\n\n"
37  "Copyrights by any strange people\n\n"
38  "(C) copyright 2007-2011, 2013 my favourite company Google\n\n"
39  "(C) 2007-2011, 2013 my favourite company Google\n\n"
40  "if (c) { return -1 } \n\n"
41  "Written by: me, myself and Irene.\n\n"
42  "Authors all the people at ABC\n\n"
43  "<author>Author1</author>"
44  "<head>All the people</head>"
45  "<author>Author1 Author2 Author3</author>"
46  "<author>Author4</author><b>example</b>"
47  "Apache\n\n"
48  "This file is protected under pants 1 , 2 ,3\n\n"
49  "Do not modify this document\n\n"
50  "the shuttle is a space vehicle designed by NASA\n\n"
51  "visit http://mysite.org/FAQ or write to info@mysite.org\n\n"
52  "maintained by benjamin drieu <benj@debian.org>\n\n"
53  "* Copyright (c) 1989, 1993\n" // Really just one newline here!
54  "* The Regents of the University of California. All rights reserved.\n\n"
55  "to be licensed as a whole"
56  "/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */";
57 
58 class scannerTestSuite : public CPPUNIT_NS :: TestFixture {
59  CPPUNIT_TEST_SUITE (scannerTestSuite);
60  CPPUNIT_TEST (copyscannerTest);
61  CPPUNIT_TEST (copyscannerDotPrefixedNameTest);
62  CPPUNIT_TEST (copyscannerBracketedYearTest);
63  CPPUNIT_TEST (copyscannerBracketedYearNoiseTest);
64  CPPUNIT_TEST (copyscannerBracketedYearBoundariesTest);
65  CPPUNIT_TEST (copyscannerCopySymByHolderTest);
66  CPPUNIT_TEST (copyscannerBareKeywordDiscardTest);
67  CPPUNIT_TEST (copyscannerCopyrightedStatementTest);
68  CPPUNIT_TEST (copyscannerCamelCaseHolderTest);
69  CPPUNIT_TEST (copyscannerBinaryNoiseTest);
70  CPPUNIT_TEST (copyscannerSpdxFullLineTest);
71  CPPUNIT_TEST (copyscannerSpdxArrayTest);
72  CPPUNIT_TEST (copyscannerProseExceptionTest);
73  CPPUNIT_TEST (regAuthorTest);
74  CPPUNIT_TEST (regIpraTest);
75  CPPUNIT_TEST (regEccTest);
76  CPPUNIT_TEST (regUrlTest);
77  CPPUNIT_TEST (regEmailTest);
78  CPPUNIT_TEST (regEmailReservedDomainTest);
79  CPPUNIT_TEST (regKeywordTest);
80  CPPUNIT_TEST (cleanEntries);
81 
82  CPPUNIT_TEST_SUITE_END ();
83 
84 private:
92  void scannerTest (const scanner& sc, const char* content, const string& type, list<const char*> expectedStrings)
93  {
94  list<match> matches;
95  list<match> expected;
96  sc.ScanString(content, matches);
97 
98  for (auto s = expectedStrings.begin(); s != expectedStrings.end(); ++s)
99  {
100  const char * p = strstr(content, *s);
101  if (p)
102  {
103  int pos = p - content;
104  expected.push_back(match(pos, pos+strlen(*s), type));
105  }
106  // else: expected string is not contained in original string
107  }
108  CPPUNIT_ASSERT_EQUAL(expected, matches);
109  }
110 
111 protected:
120  {
121  // Test copyright matcher
123 
124  scannerTest(sc, testContent, "statement", { "© 2007 Hugh Jackman",
125  "Copyright 2004 my company",
126  "Copyrights by any strange people",
127  "(C) copyright 2007-2011, 2013 my favourite company Google",
128  "(C) 2007-2011, 2013 my favourite company Google",
129  "Copyright (c) 1989, 1993\n* The Regents of the University of California."
130  });
131  }
132 
138  {
140  // © followed by a dot-prefixed name (.NET) must be fully preserved
141  const char* content1 = "Copyright \xc2\xa9 .NET Foundation and contributors\n";
142  scannerTest(sc, content1, "statement",
143  {"Copyright \xc2\xa9 .NET Foundation and contributors"});
144 
145  // Standalone © (no 'copyright' keyword) with dot-prefixed name
146  const char* content2 = "\xc2\xa9 .NET Foundation and contributors\n";
147  scannerTest(sc, content2, "statement",
148  {"\xc2\xa9 .NET Foundation and contributors"});
149 
150  // Year-qualified form must still work
151  const char* content3 = "Copyright \xc2\xa9 2021 .NET Foundation\n";
152  scannerTest(sc, content3, "statement",
153  {"Copyright \xc2\xa9 2021 .NET Foundation"});
154  }
155 
161  {
163  const char* valid[] = {
164  "Copyright (c) [2021] [Marvin Countryman]",
165  "Copyright (C) [1999] Marvin Countryman",
166  "Copyright (c)[2021] [Marvin Countryman]",
167  "Copyright (c)\t[ 2021 ] [Marvin Countryman]",
168  "Copyright (c) [\t2021\t] [Marvin Countryman]",
169  "Copyright \xc2\xa9 [2021] [Marvin Countryman]",
170  "Copyright &copy; [2021] [Marvin Countryman]",
171  "Copyrighted (C) [2021] [Marvin Countryman]",
172  "Copyright (c) 2021 [Marvin Countryman]",
173  "Copyright [2021] [Marvin Countryman]",
174  "Copyright (c) 2021 Marvin Countryman"
175  };
176 
177  for (const char* statement : valid)
178  {
179  for (const char* ending : {"", "\n"})
180  {
181  list<match> matches;
182  sc.ScanString(string(statement) + ending, matches);
183  const string message = string("Expected full active match for: ") + statement;
184  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, (size_t)1, matches.size());
185  const match& finding = matches.front();
186  CPPUNIT_ASSERT_MESSAGE(message, finding.is_enabled);
187  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, string("statement"), finding.type);
188  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, 0, finding.start);
189  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, (int)strlen(statement), finding.end);
190  }
191  }
192  }
193 
199  {
201  const char* noise[] = {
202  "Copyright (c) [year] [name]\n",
203  "Copyright (c) [yyyy] [name]\n",
204  "Copyright (c) [Marvin Countryman]\n",
205  "Copyright (c) [c] [name]\n",
206  "Copyright (c) [] [name]\n",
207  "Copyright (c) [202] [name]\n",
208  "Copyright (c) [20210] [name]\n",
209  "Copyright (c) [2021suffix] [name]\n",
210  "Copyright (c) [2021 [name]\n",
211  "Copyright (c) [[2021]] [name]\n",
212  "Copyright (c) {year} {name}\n",
213  "Copyright (c) <year> <name>\n",
214  "Copyright (c) $year $name\n",
215  "Copyright (c) %year% %name%\n"
216  };
217 
218  for (const char* statement : noise)
219  {
220  list<match> matches;
221  sc.ScanString(statement, matches);
222  for (const auto& finding : matches)
223  CPPUNIT_ASSERT_MESSAGE(
224  string("Expected no active match for: ") + statement,
225  !finding.is_enabled);
226  }
227  }
228 
234  {
236  const char* content =
237  "// Copyright (c) [2021] [Marvin Countryman]. All rights reserved.\n"
238  "// Copyright (c) 2022 Another Company\n";
239  scannerTest(sc, content, "statement", {
240  "Copyright (c) [2021] [Marvin Countryman].",
241  "Copyright (c) 2022 Another Company"
242  });
243 
244  list<match> matches;
245  sc.ScanString(content, matches);
246  for (const auto& finding : matches)
247  CPPUNIT_ASSERT_MESSAGE("Both copyright statements must stay active",
248  finding.is_enabled);
249  }
250 
257  {
259  const char* valid[] = {
260  "Copyright(c) by Mei Qingguang",
261  "Copyright (c) by Mei Qingguang",
262  "Copyright (C) by Heiko Eissfeldt",
263  "Copyright \xc2\xa9 by Mei Qingguang"
264  };
265 
266  for (const char* statement : valid)
267  {
268  for (const char* ending : {"", "\n"})
269  {
270  list<match> matches;
271  sc.ScanString(string(statement) + ending, matches);
272  const string message = string("Expected full active match for: ") + statement;
273  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, (size_t)1, matches.size());
274  const match& finding = matches.front();
275  CPPUNIT_ASSERT_MESSAGE(message, finding.is_enabled);
276  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, 0, finding.start);
277  CPPUNIT_ASSERT_EQUAL_MESSAGE(message, (int)strlen(statement), finding.end);
278  }
279  }
280 
281  // Full MIT header: the grant text must be stripped, holder kept.
282  const char* mit =
283  "This software is licensed under the MIT License.\n\n"
284  "Copyright(c) by Mei Qingguang\n\n"
285  "Permission is hereby granted, free of charge, to any person obtaining a copy\n"
286  "of this software and associated documentation files (the \"Software\"), to deal\n"
287  "in the Software without restriction.\n";
288  scannerTest(sc, mit, "statement", {"Copyright(c) by Mei Qingguang"});
289 
290  // "by" alone still leaves nothing to keep.
291  const char* bare[] = {"Copyright (c) by\n", "(c) by\n"};
292  for (const char* statement : bare)
293  {
294  list<match> matches;
295  sc.ScanString(statement, matches);
296  for (const auto& finding : matches)
297  CPPUNIT_ASSERT_MESSAGE(
298  string("Expected no active match for: ") + statement,
299  !finding.is_enabled);
300  }
301  }
302 
308  {
310 
311  // All bare-keyword variants must produce NO match
312  const char* bare[] = {
313  "copyright\n",
314  "Copyright\n",
315  "COPYRIGHT\n",
316  "Copyrights\n",
317  nullptr
318  };
319  for (int i = 0; bare[i]; ++i)
320  {
321  list<match> matches;
322  sc.ScanString(bare[i], matches);
323  CPPUNIT_ASSERT_MESSAGE(
324  string("Expected no match for bare keyword: ") + bare[i],
325  matches.empty());
326  }
327 
328  // Strings with real content must still produce exactly one match each
329  const char* valid[] = {
330  "Copyright 2021 .NET Foundation\n",
331  "Copyright (c) 2004 My Company\n",
332  "Copyright \xc2\xa9 .NET Foundation and contributors\n",
333  nullptr
334  };
335  for (int i = 0; valid[i]; ++i)
336  {
337  list<match> matches;
338  sc.ScanString(valid[i], matches);
339  CPPUNIT_ASSERT_MESSAGE(
340  string("Expected one match for valid copyright: ") + valid[i],
341  matches.size() == 1);
342  }
343  }
344 
351  {
353 
354  // All must produce exactly one active match
355  const char* valid[] = {
356  "Copyrighted (C) 1994 Normunds Saumanis (normunds@rx.tech.swh.lv)\n",
357  "Copyrighted (C) 1994, 1995, 1996 Normunds Saumanis (normunds@fi.ibm.com)\n",
358  "copyrighted (C) 1993 by Hartmut Schirmer\n",
359  "copyrighted 1992 by Mark Adler version c10p1, 10 January 1993\n",
360  "copyrighted 1990 Mark Adler\n",
361  "Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)\n",
362  "Copyright (C) Torres Martinez\n",
363  "Copyright (C) Tobias Schmidt\n",
364  "Copyright (C) Tomas Novak\n",
365  nullptr
366  };
367  for (int i = 0; valid[i]; ++i)
368  {
369  list<match> matches;
370  sc.ScanString(valid[i], matches);
371  // Must have at least one match and every match must be active
372  CPPUNIT_ASSERT_MESSAGE(
373  string("Expected active match for: ") + valid[i],
374  !matches.empty() && matches.front().is_enabled);
375  }
376  }
377 
388  {
390 
391  // Holder names beginning with "to" in any casing must stay active
392  const char* holders[] = {
393  "Copyright TOSHIBA CORPORATION, 2022. Part of the SW360 Portal Project.\n",
394  "Copyright Toshiba Software Development (Vietnam) Co., Ltd., 2022. Part of the SW360 Portal Project.\n",
395  "Copyright (C) TOSHIBA CORPORATION, 2025. Part of the SW360 Frontend Project.\n",
396  "Copyright (C) Toshiba Software Development (Vietnam) Co., Ltd., 2025. Part of the SW360 Frontend Project.\n",
397  "Copyright TOSHIBA TEC CORPORATION, 2023\n",
398  "Copyright TORONTO DOMINION BANK, 2019\n",
399  "Copyright TOYOTA MOTOR CORPORATION, 2018\n",
400  "Copyright TOMTOM INTERNATIONAL BV, 2021\n",
401  nullptr
402  };
403  for (int i = 0; holders[i]; ++i)
404  {
405  list<match> matches;
406  sc.ScanString(holders[i], matches);
407  CPPUNIT_ASSERT_MESSAGE(
408  string("Expected active match for holder: ") + holders[i],
409  !matches.empty() && matches.front().is_enabled);
410  }
411 
412  // Genuine camelCase identifiers must still be deactivated
413  const char* identifiers[] = {
414  "Copyright.ToString() returns the assembly attribute\n",
415  "copyright.ToArray().Select(x => x.Holder)\n",
416  "Copyright ToUpperInvariant helper for holder names\n",
417  nullptr
418  };
419  for (int i = 0; identifiers[i]; ++i)
420  {
421  list<match> matches;
422  sc.ScanString(identifiers[i], matches);
423  bool hasActive = !matches.empty() && matches.front().is_enabled;
424  CPPUNIT_ASSERT_MESSAGE(
425  string("Expected no active match for identifier: ") + identifiers[i],
426  !hasActive);
427  }
428  }
429 
436  {
438 
439  // Each string is © + short ASCII run + non-ASCII noise.
440  // None must produce an active match.
441  const char* noise[] = {
442  // 3-char ASCII prefix then non-ASCII
443  "\xc2\xa9 sjw\xc2\xa8noise\n",
444  "\xc2\xa9 OMr\xc2\xa5more\n",
445  "\xc2\xa9 tGa\xc3\x89garbage\n",
446  // 4-char ASCII prefix then non-ASCII
447  "\xc2\xa9 ZgU,\xc2\xb5garbage\n",
448  "\xc2\xa9 VJs0\xc3\x93noise\n",
449  // 7-char ASCII prefix then non-ASCII
450  "\xc2\xa9 NuXnHl{\xc2\xa4" "noise\n",
451  // 8-char ASCII prefix then non-ASCII
452  "\xc2\xa9 KtCtdy\x22s\xc3\xa8noise\n",
453  nullptr
454  };
455 
456  for (int i = 0; noise[i]; ++i)
457  {
458  list<match> matches;
459  sc.ScanString(noise[i], matches);
460  bool hasActive = !matches.empty() && matches.front().is_enabled;
461  CPPUNIT_ASSERT_MESSAGE(
462  string("Expected no active match for binary noise string #") + to_string(i),
463  !hasActive);
464  }
465  }
466 
473  {
475 
476  // Normal closed array: 1 deactivated header + 3 active elements
477  {
478  const char content[] =
479  "SPDX-FileCopyrightText = [\n"
480  "\"2026 Fraunhofer-Institut f\xC3\xBCr Produktionstechnik und Automatisierung IPA\",\n"
481  "\"2026 Hilscher Gesellschaft f\xC3\xBCr Systemautomation mbH\",\n"
482  "\"2026 Siemens AG\",\n"
483  "]\n";
484 
485  list<match> matches;
486  sc.ScanString(content, matches);
487 
488  CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected 4 matches total", (size_t)4, matches.size());
489 
490  auto it = matches.begin();
491  CPPUNIT_ASSERT_MESSAGE("Header must be inactive", !it->is_enabled);
492  ++it;
493  for (int i = 1; i <= 3; ++i, ++it)
494  CPPUNIT_ASSERT_MESSAGE(
495  string("Array element ") + to_string(i) + " must be active", it->is_enabled);
496  }
497 
498  // Malformed array (no closing ]): scan must continue past the block and
499  // still detect copyright statements that follow it.
500  {
501  const char content[] =
502  "SPDX-FileCopyrightText = [\n"
503  "\"2026 Company A\",\n"
504  "\"2026 Company B\",\n"
505  // no closing ]
506  "Copyright 2021 Google LLC\n";
507 
508  list<match> matches;
509  sc.ScanString(content, matches);
510 
511  bool foundGoogle = false;
512  for (auto& m : matches) {
513  int len = m.end - m.start;
514  if (len > 0 && strncmp(content + m.start, "Copyright 2021 Google", 21) == 0)
515  foundGoogle = true;
516  }
517  CPPUNIT_ASSERT_MESSAGE(
518  "Copyright after unclosed SPDX array must still be detected", foundGoogle);
519  }
520  }
521 
529  {
531 
532  // Two lines with German umlauts (ü = \xC3\xBC), one plain ASCII line.
533  const char content[] =
534  "// SPDX-FileCopyrightText: 2026 Fraunhofer-Institut f\xC3\xBCr Produktionstechnik und Automatisierung IPA\n"
535  "// SPDX-FileCopyrightText: 2026 Hilscher Gesellschaft f\xC3\xBCr Systemautomation mbH\n"
536  "// SPDX-FileCopyrightText: 2026 Siemens AG\n";
537 
538  list<match> matches;
539  sc.ScanString(content, matches);
540 
541  CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected 3 SPDX matches", (size_t)3, matches.size());
542 
543  // Verify each match is active and its end position reaches the line's '\n'
544  const char* lineStarts[3];
545  lineStarts[0] = strstr(content, "SPDX-FileCopyrightText: 2026 Fraunhofer");
546  lineStarts[1] = strstr(content, "SPDX-FileCopyrightText: 2026 Hilscher");
547  lineStarts[2] = strstr(content, "SPDX-FileCopyrightText: 2026 Siemens");
548 
549  int i = 0;
550  for (auto& m : matches)
551  {
552  CPPUNIT_ASSERT_MESSAGE(
553  string("Match ") + to_string(i) + " must be active",
554  m.is_enabled);
555 
556  int expectedStart = lineStarts[i] - content;
557  int expectedEnd = (int)(strchr(lineStarts[i], '\n') - content);
558 
559  CPPUNIT_ASSERT_EQUAL_MESSAGE(
560  string("Match ") + to_string(i) + " start",
561  expectedStart, m.start);
562  CPPUNIT_ASSERT_EQUAL_MESSAGE(
563  string("Match ") + to_string(i) + " end must reach line end",
564  expectedEnd, m.end);
565  ++i;
566  }
567  }
568 
583  {
585 
586  // All must produce NO active match (either deactivated or discarded)
587  const char* prose[] = {
588  "copyrights appearing in this test file\n",
589  "copyrights appears in the documentation\n",
590  "COPYRIGHT TO DETECT This section uses the standard header\n",
591  "copyright work that can be distributed\n",
592  "copyright protection under the terms of this License\n",
593  "copyrighted interfaces, the original copyright holder\n",
594  "copyright in the work, if the License is applied\n",
595  "copyright of this Package, but belong to whoever generated\n",
596  "copyright on material distributed under this License\n",
597  nullptr
598  };
599  for (int i = 0; prose[i]; ++i)
600  {
601  list<match> matches;
602  sc.ScanString(prose[i], matches);
603  bool hasActive = !matches.empty() && matches.front().is_enabled;
604  CPPUNIT_ASSERT_MESSAGE(
605  string("Expected no active match for prose: ") + prose[i],
606  !hasActive);
607  }
608 
609  // These must remain KEPT — year or (C)+year acts as holder separator
610  const char* valid[] = {
611  "Copyright (C) 2021 Toronto Inc.\n",
612  "Copyright 2021 Workday Inc.\n",
613  "Copyright (C) 2021 Interface Logic Inc.\n",
614  "Copyright (C) 2021 In-N-Out Burgers\n",
615  nullptr
616  };
617  for (int i = 0; valid[i]; ++i)
618  {
619  list<match> matches;
620  sc.ScanString(valid[i], matches);
621  CPPUNIT_ASSERT_MESSAGE(
622  string("Expected active match for: ") + valid[i],
623  !matches.empty() && matches.front().is_enabled);
624  }
625  }
626 
635  {
636  regexScanner sc("author", "copyright");
637  scannerTest(sc, testContent, "author", {
638  "Written by: me, myself and Irene.",
639  "Authors all the people at ABC",
640  "Author1",
641  "Author1 Author2 Author3",
642  "Author4",
643  "maintained by benjamin drieu <benj@debian.org>"
644  });
645  }
646 
654  void regIpraTest () {
655  regexScanner sc("ipra", "ipra");
656  scannerTest(sc, testContent, "ipra", { "US patents 1 , 2 ,3" });
657  }
658 
666  void regEccTest () {
667  regexScanner sc("ecc", "ecc");
668  scannerTest(sc, testContent, "ecc", { "space vehicle designed by NASA" });
669  }
670 
678  void regUrlTest () {
679  regexScanner sc("url", "copyright");
680  scannerTest(sc, testContent, "url", { "http://mysite.org/FAQ" });
681  }
682 
690  void regEmailTest () {
691  regexScanner sc("email", "copyright",1);
692  scannerTest(sc, testContent, "email", { "info@mysite.org", "benj@debian.org" });
693  }
694 
704  const char content[] =
705  "alice@example.com\n"
706  "<bob@example.net>\n"
707  "(carol@example.org)\n"
708  "dave@server.test\n"
709  "erin@host.invalid\n"
710  "grace@sub.example.com\n"
711  "frank@realcompany.de\n"
712  "john@myexample.com\n"
713  "maria@example.community\n"
714  "Contact paul@kernel.org.\n"
715  "sam@mail.co.uk\n";
716  regexScanner sc("email", "copyright", 1);
717  scannerTest(sc, content, "email", { "frank@realcompany.de",
718  "john@myexample.com", "maria@example.community", "paul@kernel.org",
719  "sam@mail.co.uk" });
720  }
721 
729  void regKeywordTest () {
730  regexScanner sc("keyword", "keyword");
731  scannerTest(sc, testContent, "keyword", {"patent", "licensed as", "stolen from"});
732  }
733 
742  void cleanEntries () {
743  // Binary content
744  string actualFileContent;
745  ReadFileToString("../testdata/testdata142", actualFileContent);
746 
747  vector<string> binaryStrings;
748  std::stringstream *ss = new std::stringstream(actualFileContent);
749  string temp;
750 
751  while (std::getline(*ss, temp)) {
752  binaryStrings.push_back(temp);
753  }
754 
755  // Simulate matches. Each line is a match
756  vector<match> matches;
757  int pos = 0;
758  int size = binaryStrings.size();
759  for (int i = 0; i < size; i++)
760  {
761  int length = binaryStrings[i].length();
762  matches.push_back(
763  match(pos, pos + length, "statement"));
764  pos += length + 1;
765  }
766 
767  // Expected data
768  string expectedFileContent;
769  ReadFileToString("../testdata/testdata142_exp", expectedFileContent);
770 
771  delete(ss);
772  ss = new std::stringstream(expectedFileContent);
773  vector<string> expectedStrings;
774  while (std::getline(*ss, temp)) {
775  expectedStrings.push_back(temp);
776  }
777 
778  vector<string> actualStrings;
779  for (size_t i = 0; i < matches.size(); i ++)
780  {
781  actualStrings.push_back(cleanMatch(actualFileContent, matches[i]));
782  }
783 
784  CPPUNIT_ASSERT(expectedStrings == actualStrings);
785  }
786 };
787 
788 CPPUNIT_TEST_SUITE_REGISTRATION( scannerTestSuite );
Implementation of scanner class for copyright.
Definition: copyscan.hpp:39
void ScanString(const string &s, list< match > &results) const
Scan a given string for copyright statements.
Definition: copyscan.cc:63
Provides a regex scanner using predefined regexs.
Definition: regscan.hpp:21
void copyscannerBracketedYearTest()
Preserve bracketed numeric years after a copyright symbol.
void copyscannerCamelCaseHolderTest()
Regression: REG_EXCEPTION_COPY carries a To[A-Z][a-zA-Z]{4,} branch to skip camelCase identifiers suc...
void copyscannerBracketedYearBoundariesTest()
Preserve offsets and separation from the following statement.
void regIpraTest()
Test Ipra scanner.
void copyscannerCopyrightedStatementTest()
Regression: "copyrighted" statements and names like "Tom" must not be falsely deactivated by REG_EXCE...
void copyscannerBinaryNoiseTest()
Regression: binary-file content with a short ASCII prefix before non-ASCII bytes must not be reported...
void regKeywordTest()
Test copyright scanner for keywords.
void copyscannerCopySymByHolderTest()
A copyright symbol followed by "by <holder>" without a year must not be stripped down to a bare keywo...
void copyscannerSpdxFullLineTest()
Regression: SPDX-FileCopyrightText entries must be detected as individual single-line statements and ...
void scannerTest(const scanner &sc, const char *content, const string &type, list< const char * > expectedStrings)
Runs scanner on content and check matches against expectedStrings.
void copyscannerBareKeywordDiscardTest()
Test that bare copyright keywords produce no matches.
void copyscannerDotPrefixedNameTest()
Test copyright scanner with dot-prefixed names like .NET Foundation.
void regEmailReservedDomainTest()
Test email scanner skips reserved domains (RFC 2606)
void regUrlTest()
Test copyright scanner for URL.
void regEmailTest()
Test copyright scanner for email.
void copyscannerTest()
Test copyright scanner.
void copyscannerBracketedYearNoiseTest()
Brackets must not exempt placeholders or noise from cleanup.
void regEccTest()
Test ECC scanner.
void copyscannerProseExceptionTest()
Regression: license-prose strings that contain "copyright" as a common noun must be deactivated,...
void regAuthorTest()
Test copyright scanner for author.
void cleanEntries()
Test cleanMatch() to remove non-UTF8 text and extra spaces.
void copyscannerSpdxArrayTest()
Regression: SPDX-FileCopyrightText = [...] TOML array format must yield one active match per quoted e...
Abstract class to provide interface to scanners.
Definition: scanners.hpp:59
virtual void ScanString(const string &s, list< match > &results) const =0
Scan the given string and add matches to results.
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
int valid
If the information stored in buffer is valid.
bool ReadFileToString(const string &fileName, string &out)
Utility: read file to string from scanners.h.
Definition: scanners.cc:21
Store the results of a regex match.
Definition: scanners.hpp:28
const int start
Definition: scanners.hpp:35
const int end
Definition: scanners.hpp:35
bool is_enabled
Definition: scanners.hpp:46
std::ostream & operator<<(std::ostream &os, const std::vector< int > &x)
<< operator overload to appends a vector to an ostream object
Definition: testUtils.hpp:27