Repository: eclipse-bluechi/bluechi (language: python)

Issue:
Linting
## Please describe what you would like to see

In order to statically analyze and enforce best practice rules, there should be linter in place - available to run locally and in the CI. 

## Please describe the solution you'd like

[clang-tidy](https://clang.llvm.org/extra/clang-tidy/) seems to be a good option for this. There should be

- a first, initial rule set, 
- a Makefile target , 
- and an integration into the CI
 
implemented. 



Discussion / hints:

Fix patch:
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000000..8eb81445b8
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,21 @@
+---
+Checks: >
+    *,
+    -llvm-header-guard,
+    -llvmlibc-restrict-system-libc-headers,
+    -cert-err33-c,
+    -cert-dcl37-c,
+    -cert-dcl51-cpp,
+    -bugprone-reserved-identifier,
+    -readability-identifier-length,
+    -concurrency-mt-unsafe,
+    -google-readability-todo,
+    -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+    -altera-unroll-loops,
+    -altera-id-dependent-backward-branch,
+    -bugprone-easily-swappable-parameters,
+
+
+# Turn all the warnings from the checks above into errors.,
+WarningsAsErrors: "*"
+HeaderFilterRegex: ""
diff --git a/Makefile b/Makefile
index 32a5572a4b..ba47830082 100644
--- a/Makefile
+++ b/Makefile
@@ -9,4 +9,10 @@ check-fmt:
 		if [ $$? -ne 0 ] ; then \
 			exit 1 ; \
 		fi ; \
-	done
\ No newline at end of file
+	done
+
+lint: 
+	find . -name "*.[ch]" ! -path "./src/ini/*" ! -path "./test/**" -print0 | xargs -0 -n 1 -I {} clang-tidy --quiet {} -- -D_GNU_SOURCE
+
+lint-fix: 
+	find . -name "*.[ch]" ! -path "./src/ini/*" ! -path "./test/**" -print0 | xargs -0 -n 1 -I {} clang-tidy --quiet {} --fix -- -D_GNU_SOURCE
diff --git a/README.md b/README.md
index ffdba7ff35..eb3967b76a 100644
--- a/README.md
+++ b/README.md
@@ -30,9 +30,7 @@ sudo dnf install -y clang-tools-extra gcc make meson systemd-devel
 
 ### Code Style
 
-`clang-format` is used to enforce a unified code style. For setup instructions, please refer to the [official Clang getting started guide](https://clang.llvm.org/get_started.html).
-
-Once `clang-format` is set up, all source files can be formatted via:
+[clang-format](https://clang.llvm.org/docs/ClangFormat.html) is used to enforce a unified code style. All source files can be formatted via:
 ```bash
 make fmt
 ```
@@ -42,6 +40,18 @@ A formatting check of existing files can be executed by:
 make check-fmt
 ```
 
+### Linting
+
+[clang-tidy](https://clang.llvm.org/extra/clang-tidy/) is used for static analysis. All source files can be checked via:
+```bash
+make lint
+```
+
+Some errors detected by `clang-tidy` can be fixed automatically via: 
+```bash
+make lint-fix
+```
+
 ### Build
 
 The project is using [meson](https://mesonbuild.com/) build system.
diff --git a/src/common/memory.h b/src/common/memory.h
index bf90dcb096..637e0814dd 100644
--- a/src/common/memory.h
+++ b/src/common/memory.h
@@ -11,7 +11,7 @@ static inline void *steal_pointer(void *ptr) {
         return p;
 }
 
-static inline void closep(int *fd) {
+static inline void closep(const int *fd) {
         if (*fd >= 0) {
                 close(*fd);
         }
diff --git a/src/common/parse-util.h b/src/common/parse-util.h
index 683b9a2a52..85fecc8c12 100644
--- a/src/common/parse-util.h
+++ b/src/common/parse-util.h
@@ -10,8 +10,9 @@ int parse_long(const char *in, long *val) {
                 return 1;
         }
 
-        char *ptr;
-        *val = strtol(in, &ptr, 10);
+        const int decimalBase = 10;
+        char *ptr = NULL;
+        *val = strtol(in, &ptr, decimalBase);
         if (strcmp(ptr, "") != 0) {
                 return 1;
         }
diff --git a/src/node/dbus.c b/src/node/dbus.c
index f2c5edf245..613f5d7786 100644
--- a/src/node/dbus.c
+++ b/src/node/dbus.c
@@ -5,7 +5,8 @@
 #include <stdio.h>
 
 int setup_peer_dbus(sd_bus *dbus, const struct sockaddr_in *addr) {
-        int r;
+        int r = 0;
+
         r = sd_bus_new(&dbus);
         if (r < 0) {
                 fprintf(stderr, "Failed to create bus: %s\n", strerror(-r));
diff --git a/src/node/node.c b/src/node/node.c
index 804e3a1fef..133a1b8a76 100644
--- a/src/node/node.c
+++ b/src/node/node.c
@@ -17,7 +17,7 @@ int main(int argc, char *argv[]) {
 
         get_opts(argc, argv, &host);
 
-        int r;
+        int r = 0;
         _cleanup_sd_event_ sd_event *event = NULL;
         r = sd_event_default(&event);
         if (r < 0) {
diff --git a/src/node/opt.c b/src/node/opt.c
index aeb285de29..624f38c1a2 100644
--- a/src/node/opt.c
+++ b/src/node/opt.c
@@ -7,8 +7,12 @@
 #include <stdlib.h>
 
 void get_opts(int argc, char *argv[], struct sockaddr_in *orchAddr) {
-        int opt, r, port;
-        int hflag, pflag;
+        int r = 0;
+        int opt = 0;
+        int port = 0;
+        int hflag = 0;
+        int pflag = 0;
+
         while ((opt = getopt(argc, argv, "h:p:")) != -1) {
                 switch (opt) {
                 case 'h':
diff --git a/src/orch/controller.c b/src/orch/controller.c
index 42ca4372bd..573ccbd276 100644
--- a/src/orch/controller.c
+++ b/src/orch/controller.c
@@ -43,16 +43,17 @@ int create_master_socket(const int port) {
         return fd;
 }
 
+// NOLINTNEXTLINE
 static int accept_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         _cleanup_fd_ int nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
         if (nfd < 0) {
-                if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)
+                if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
                         return 0;
-                else {
-                        int errsv = errno;
-                        fprintf(stderr, "Failed to accept: %m\n");
-                        return -errsv;
                 }
+
+                int errsv = errno;
+                fprintf(stderr, "Failed to accept: %m\n");
+                return -errsv;
         }
 
         // TODO: setup peer dbus, incl. vtable with services, signals, properties
diff --git a/src/orch/opt.c b/src/orch/opt.c
index 66431aa26c..f9cff49ba2 100644
--- a/src/orch/opt.c
+++ b/src/orch/opt.c
@@ -5,7 +5,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 void get_opts(int argc, char *argv[], int *ctrlPort, char **configPath) {
-        int opt;
+        int opt = 0;
         int pflag = 0;
 
         while ((opt = getopt(argc, argv, "p:c:")) != -1) {
diff --git a/src/orch/orch.c b/src/orch/orch.c
index ca2172db06..455bf2d930 100644
--- a/src/orch/orch.c
+++ b/src/orch/orch.c
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 
 /* A function that takes care of printing the lines of the ini file  */
+// NOLINTNEXTLINE
 static int ini_handler_func(void *user, const char *section, const char *name, const char *value) {
         printf("[%s] %s = %s\n", section, name, value);
         return EXIT_FAILURE;
@@ -15,7 +16,7 @@ static int ini_handler_func(void *user, const char *section, const char *name, c
 int main(int argc, char *argv[]) {
         fprintf(stdout, "Hello from orchestrator!\n");
 
-        int port;
+        int port = 0;
         _cleanup_free_ char *configPath = NULL;
 
         get_opts(argc, argv, &port, &configPath);


Test patch:
diff --git a/run-tests.sh b/run-tests.sh
deleted file mode 100644
index df4301bede..0000000000
--- a/run-tests.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-
-array=( client common node orch )
-for i in "${array[@]}"
-do
-    tests=$(ls ./test/$i/*_test.c 2>/dev/null)
-
-    test_binaries=()
-    for t in $tests
-    do
-        n=${t::len-2}
-        # extend this by additional c files as tests grow
-        gcc -D_GNU_SOURCE $t -g -O1 -Wall -o $n
-        test_binaries+=($n)
-    done
-
-    for t in ${test_binaries[@]}
-    do
-        echo "Running $t..."
-        RED='\033[0;31m'
-        NC='\033[0m'
-        printf "${RED}"
-        ./$t
-        printf "${NC}"
-        rm $t
-    done
-
-done