You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							77 lines
						
					
					
						
							2.3 KiB
						
					
					
				
			
		
		
	
	
							77 lines
						
					
					
						
							2.3 KiB
						
					
					
				#!/usr/bin/env python3
 | 
						|
import os
 | 
						|
import glob
 | 
						|
import pytest
 | 
						|
import shutil
 | 
						|
import subprocess
 | 
						|
import tempfile
 | 
						|
import random
 | 
						|
 | 
						|
HERE = os.path.abspath(os.path.dirname(__file__))
 | 
						|
ROOT = os.path.join(HERE, "../../")
 | 
						|
 | 
						|
IGNORED_PATHS = (
 | 
						|
  'board/obj',
 | 
						|
  'board/jungle',
 | 
						|
  'board/stm32h7/inc',
 | 
						|
  'board/fake_stm.h',
 | 
						|
 | 
						|
  # bootstub only files
 | 
						|
  'board/flasher.h',
 | 
						|
  'board/bootstub.c',
 | 
						|
  'board/bootstub_declarations.h',
 | 
						|
  'board/stm32h7/llflash.h',
 | 
						|
)
 | 
						|
 | 
						|
mutations = [
 | 
						|
  (None, None, False),  # no mods, should pass
 | 
						|
  ("board/stm32h7/llfdcan.h", "s/return ret;/if (true) { return ret; } else { return false; }/g", True),
 | 
						|
]
 | 
						|
 | 
						|
patterns = [
 | 
						|
  # misra-c2012-13.3
 | 
						|
  "$a void test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}",
 | 
						|
  # misra-c2012-13.4
 | 
						|
  "$a int test(int x, int y) { return (x=2) && (y=2); }",
 | 
						|
  # misra-c2012-13.5
 | 
						|
  "$a void test(int tmp) { if (true && tmp++) {;} }",
 | 
						|
  # misra-c2012-13.6
 | 
						|
  "$a void test(int tmp) { if (sizeof(tmp++)) {;} }",
 | 
						|
  # misra-c2012-14.1
 | 
						|
  "$a void test(float len) { for (float j = 0; j < len; j++) {;} }",
 | 
						|
  # misra-c2012-14.4
 | 
						|
  "$a void test(int len) { if (len - 8) {;} }",
 | 
						|
  # misra-c2012-16.4
 | 
						|
  r"$a void test(int temp) {switch (temp) { case 1: ; }}\n",
 | 
						|
  # misra-c2012-17.8
 | 
						|
  "$a void test(int cnt) { for (cnt=0;;cnt++) {;} }",
 | 
						|
  # misra-c2012-20.4
 | 
						|
  r"$a #define auto 1\n",
 | 
						|
  # misra-c2012-20.5
 | 
						|
  r"$a #define TEST 1\n#undef TEST\n",
 | 
						|
]
 | 
						|
 | 
						|
all_files = glob.glob('board/**', root_dir=ROOT, recursive=True)
 | 
						|
files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS)]
 | 
						|
assert len(files) > 50, all(d in files for d in ('board/main.c', 'board/stm32h7/llfdcan.h'))
 | 
						|
 | 
						|
for p in patterns:
 | 
						|
  mutations.append((random.choice(files), p, True))
 | 
						|
 | 
						|
# TODO: remove sampling once test_misra.sh is faster
 | 
						|
mutations = random.sample(mutations, 2)
 | 
						|
 | 
						|
@pytest.mark.parametrize("fn, patch, should_fail", mutations)
 | 
						|
def test_misra_mutation(fn, patch, should_fail):
 | 
						|
  with tempfile.TemporaryDirectory() as tmp:
 | 
						|
    shutil.copytree(ROOT, tmp + "/panda", dirs_exist_ok=True)
 | 
						|
 | 
						|
    # apply patch
 | 
						|
    if fn is not None:
 | 
						|
      r = os.system(f"cd {tmp}/panda && sed -i '{patch}' {fn}")
 | 
						|
      assert r == 0
 | 
						|
 | 
						|
    # run test
 | 
						|
    r = subprocess.run("SKIP_TABLES_DIFF=1 panda/tests/misra/test_misra.sh", cwd=tmp, shell=True)
 | 
						|
    failed = r.returncode != 0
 | 
						|
    assert failed == should_fail
 | 
						|
 |