AT_BANNER([checkpatch]) OVS_START_SHELL_HELPERS # try_checkpatch PATCH [ERRORS] # # Runs checkpatch, if installed, on the given PATCH, expecting the # specified set of ERRORS (and warnings). try_checkpatch() { # Take the patch to test from $1. Remove an initial four-space indent # from it and, if it is just headers with no body, add a null body. echo "$1" | sed 's/^ //' > test.patch if grep '---' expout >/dev/null 2>&1; then : else printf '\n---\n' >> test.patch fi # Take expected output from $2. if test -n "$2"; then echo "$2" | sed 's/^ //' > expout else : > expout fi if test -s expout; then AT_CHECK([$PYTHON3 $top_srcdir/utilities/checkpatch.py -q test.patch], [1], [stdout]) AT_CHECK([sed '/^Lines checked:/,$d' stdout], [0], [expout]) else AT_CHECK([$PYTHON3 $top_srcdir/utilities/checkpatch.py -q test.patch]) fi } OVS_END_SHELL_HELPERS AT_SETUP([checkpatch - sign-offs]) # Sign-off for single author who is also the committer. try_checkpatch \ "Author: A Commit: A Signed-off-by: A" try_checkpatch \ "Author: A Commit: A" \ "ERROR: Author A needs to sign off." # Single author but somehow the mailing list is the author. try_checkpatch \ "Author: Foo Bar via dev Commit: A Signed-off-by: A" \ "ERROR: Author should not be mailing list." # Sign-off for single author and different committer. try_checkpatch \ "Author: A Commit: B Signed-off-by: A Signed-off-by: B" try_checkpatch \ "Author: A Commit: B" \ "ERROR: Author A needs to sign off. ERROR: Committer B needs to sign off." # Sign-off for multiple authors with one author also the committer. try_checkpatch \ "Author: A Commit: A Signed-off-by: A Co-authored-by: B Signed-off-by: B" try_checkpatch \ "Author: A Commit: A Co-authored-by: B Signed-off-by: B" \ "ERROR: Author A needs to sign off." try_checkpatch \ "Author: A Commit: A Signed-off-by: A Co-authored-by: B" \ "ERROR: Co-author B needs to sign off." try_checkpatch \ "Author: A Commit: A Co-authored-by: B" \ "ERROR: Author A needs to sign off. ERROR: Co-author B needs to sign off." # Sign-off for multiple authors and separate committer. try_checkpatch \ "Author: A Commit: C Signed-off-by: A Co-authored-by: B Signed-off-by: B Signed-off-by: C" try_checkpatch \ "Author: A Commit: C Signed-off-by: A Co-authored-by: B Signed-off-by: B" \ "ERROR: Committer C needs to sign off." # Extra sign-offs: # # - If we know the committer, one extra sign-off raises a warning. # # - If we do not know the committer, two extra sign-offs raise a warning. try_checkpatch \ "Author: A Commit: C Signed-off-by: A Co-authored-by: B Signed-off-by: B Signed-off-by: C Signed-off-by: D" \ "WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: D" try_checkpatch \ "Author: A Signed-off-by: A Co-authored-by: B Signed-off-by: B Signed-off-by: C" try_checkpatch \ "Author: A Signed-off-by: A Co-authored-by: B Signed-off-by: B Signed-off-by: C Signed-off-by: D" \ "WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: C, D" # Missing committer is OK, missing author is an error. try_checkpatch \ "Author: A Signed-off-by: A" try_checkpatch \ "Commit: A Signed-off-by: A" \ "ERROR: Patch lacks author." AT_CLEANUP m4_define([COMMON_PATCH_HEADER], [dnl Author: A Signed-off-by: A --- diff --git a/$([[ ! -z "$1" ]] && echo "$1" || echo "A.c") b/$([[ ! -z "$1" ]] && echo "$1" || echo "A.c") index 0000000..1111111 100644 --- a/$([[ ! -z "$1" ]] && echo "$1" || echo "A.c") +++ b/$([[ ! -z "$1" ]] && echo "$1" || echo "A.c") @@ -1,1 +1,1 @@]) AT_SETUP([checkpatch - parenthesized constructs]) for ctr in 'if' 'while' 'switch' 'HMAP_FOR_EACH' 'BITMAP_FOR_EACH_1'; do try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (first_run) { " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr ( first_run) { " \ "ERROR: Improper whitespace around control block #8 FILE: A.c:1: $ctr ( first_run) { " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (first_run ) { " \ "ERROR: Inappropriate bracing around statement #8 FILE: A.c:1: $ctr (first_run ) { " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (first_run) " \ "ERROR: Inappropriate bracing around statement #8 FILE: A.c:1: $ctr (first_run) " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr(first_run) " \ "ERROR: Improper whitespace around control block #8 FILE: A.c:1: $ctr(first_run) " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (first_run) { /* foo */ " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (first_run) { \\ " try_checkpatch \ "COMMON_PATCH_HEADER + $ctr (a) { \\ " done AT_CLEANUP AT_SETUP([checkpatch - catastrophic backtracking]) dnl Special case this rather than using the above construct because sometimes a dnl warning needs to be generated for line lengths (f.e. when the 'while' dnl keyword is used). try_checkpatch \ "COMMON_PATCH_HEADER + if (!b_ctx_in->chassis_rec || !b_ctx_in->br_int || !b_ctx_in->ovs_idl_txn) " \ "ERROR: Inappropriate bracing around statement #8 FILE: A.c:1: if (!b_ctx_in->chassis_rec || !b_ctx_in->br_int || !b_ctx_in->ovs_idl_txn) " AT_CLEANUP AT_SETUP([checkpatch - parenthesized constructs - for]) try_checkpatch \ "COMMON_PATCH_HEADER + for (init; condition; increment) { " try_checkpatch \ "COMMON_PATCH_HEADER + for ( init; condition; increment) { " \ "ERROR: Improper whitespace around control block #8 FILE: A.c:1: for ( init; condition; increment) { " try_checkpatch \ "COMMON_PATCH_HEADER + for (init; condition; increment ) { " \ "ERROR: Inappropriate bracing around statement #8 FILE: A.c:1: for (init; condition; increment ) { " try_checkpatch \ "COMMON_PATCH_HEADER + for (init; condition; increment) " \ "ERROR: Inappropriate bracing around statement #8 FILE: A.c:1: for (init; condition; increment) " try_checkpatch \ "COMMON_PATCH_HEADER + for(init; condition; increment) " \ "ERROR: Improper whitespace around control block #8 FILE: A.c:1: for(init; condition; increment) " try_checkpatch \ "COMMON_PATCH_HEADER + for (init; condition; increment) { /* foo */ " try_checkpatch \ "COMMON_PATCH_HEADER + for (init; condition; increment) { \\ " try_checkpatch \ "COMMON_PATCH_HEADER +#define SOME_FOR_EACH(a, b, c) /* Foo. */ " AT_CLEANUP AT_SETUP([checkpatch - comments]) try_checkpatch \ "COMMON_PATCH_HEADER + a = 1; /* C style comment. */ " try_checkpatch \ "COMMON_PATCH_HEADER + /* http://URL/inside/the/comment.html */ " try_checkpatch \ "COMMON_PATCH_HEADER + a = 1; // C99 style comment. " \ "ERROR: C99 style comment #8 FILE: A.c:1: a = 1; // C99 style comment. " AT_CLEANUP AT_SETUP([checkpatch - whitespace around operator]) try_checkpatch \ "COMMON_PATCH_HEADER + if (--mcs->n_refs == 0) { " try_checkpatch \ "COMMON_PATCH_HEADER + if (--mcs->n_refs==0) { " \ "WARNING: Line lacks whitespace around operator WARNING: Line lacks whitespace around operator #8 FILE: A.c:1: if (--mcs->n_refs==0) { " AT_CLEANUP AT_SETUP([checkpatch - check misuse APIs]) try_checkpatch \ "COMMON_PATCH_HEADER([a.c]) + ovsrcu_barrier(); " \ "WARNING: Are you sure you need to use ovsrcu_barrier(), "\ "in most cases ovsrcu_synchronize() will be fine? #8 FILE: a.c:1: ovsrcu_barrier(); " try_checkpatch \ "COMMON_PATCH_HEADER([lib/ovs-rcu.c]) + ovsrcu_barrier(); " AT_CLEANUP AT_SETUP([checkpatch - check egrep / fgrep]) try_checkpatch \ "COMMON_PATCH_HEADER([tests/something.at]) +C_H_E_C_K([[ovs-vsctl show | grep -E 'my-port.*[[0-9]]$' | grep -F 'port']]) " try_checkpatch \ "COMMON_PATCH_HEADER([tests/something.at]) +C_H_E_C_K([[ovs-vsctl show | egrep 'my-port.*[[0-9]]$']]) " \ "ERROR: grep -E/-F should be used instead of egrep/fgrep #8 FILE: tests/something.at:1: C_H_E_C_K([[ovs-vsctl show | egrep 'my-port.*[[0-9]]$']]) " try_checkpatch \ "COMMON_PATCH_HEADER([tests/something.at]) +C_H_E_C_K([[ovs-vsctl show | fgrep 'my-port.*[[0-9]]$']]) " \ "ERROR: grep -E/-F should be used instead of egrep/fgrep #8 FILE: tests/something.at:1: C_H_E_C_K([[ovs-vsctl show | fgrep 'my-port.*[[0-9]]$']]) " AT_CLEANUP AT_SETUP([checkpatch - whitespace around cast]) try_checkpatch \ "COMMON_PATCH_HEADER + (int) a; " try_checkpatch \ "COMMON_PATCH_HEADER + (int)a; " \ "ERROR: Inappropriate spacing around cast #8 FILE: A.c:1: (int)a; " AT_CLEANUP AT_SETUP([checkpatch - malformed tags]) try_checkpatch \ " Author: A Acked by: foo... Signed-off-by: A" \ "ERROR: Acked-by tag is malformed. 1: Acked by: foo... " try_checkpatch \ " Author: A Reported at: foo... Signed-off-by: A" \ "ERROR: Reported-at tag is malformed. 1: Reported at: foo... " try_checkpatch \ " Author: A Reported by: foo... Signed-off-by: A" \ "ERROR: Reported-by tag is malformed. 1: Reported by: foo... " try_checkpatch \ " Author: A Requested by: foo... Signed-off-by: A" \ "ERROR: Requested-by tag is malformed. 1: Requested by: foo... " try_checkpatch \ " Author: A Reviewed by: foo... Signed-off-by: A" \ "ERROR: Reviewed-by tag is malformed. 1: Reviewed by: foo... " try_checkpatch \ " Author: A Submitted at: foo... Signed-off-by: A" \ "ERROR: Submitted-at tag is malformed. 1: Submitted at: foo... " try_checkpatch \ " Author: A Suggested by: foo... Signed-off-by: A" \ "ERROR: Suggested-by tag is malformed. 1: Suggested by: foo... " AT_CLEANUP AT_SETUP([checkpatch - Unicode code]) try_checkpatch \ "COMMON_PATCH_HEADER + if (snowman == ☃️) { /* Emoji + void НelloWorld() { /* Homoglyph + ة /* ;C++ /* BiDi " \ "ERROR: Inappropriate non-ascii characters detected. #8 FILE: A.c:1: if (snowman == ☃️) { /* Emoji ERROR: Inappropriate non-ascii characters detected. #9 FILE: A.c:2: void НelloWorld() { /* Homoglyph ERROR: Inappropriate non-ascii characters detected. #10 FILE: A.c:3: ة /* ;C++ /* BiDi " AT_CLEANUP m4_define([FIXES_TAG_ERROR], [dnl ERROR: \"Fixes\" tag is malformed. Use the following format: git log -1 --pretty=format:\"Fixes: %h (\\\"%s\\\")\" --abbrev=12 COMMIT_REF ]) AT_SETUP([checkpatch - Fixes tag]) try_checkpatch \ "Author: A Commit: A Fixes: 123456789abc (\"commit name\") Signed-off-by: A" try_checkpatch \ "Author: A Commit: A fixes: 123456789abc (\"commit name\") Signed-off-by: A" \ "FIXES_TAG_ERROR 1: fixes: 123456789abc (\"commit name\") " try_checkpatch \ "Author: A Commit: A Fixes: 12345678 (\"commit name\") Signed-off-by: A" \ "FIXES_TAG_ERROR 1: Fixes: 12345678 (\"commit name\") " try_checkpatch \ "Author: A Commit: A Fixes: 1234567890abcdef1234567890abcdef12345678 (\"commit name\") Signed-off-by: A" \ "FIXES_TAG_ERROR 1: Fixes: 1234567890abcdef1234567890abcdef12345678 (\"commit name\") " try_checkpatch \ "Author: A Commit: A Fixes: 123456789abc \"commit name\" Signed-off-by: A" \ "FIXES_TAG_ERROR 1: Fixes: 123456789abc \"commit name\" " try_checkpatch \ "Author: A Commit: A Fixes: 123456789abc (\"some very long commit name that doesn\'t fit into a single line, but should not be wrapped.\") Signed-off-by: A" \ "FIXES_TAG_ERROR 1: Fixes: 123456789abc (\"some very long commit name that doesn\'t fit into " AT_CLEANUP