daha büyük CTEST_PARALLEL_LEVEL için cmake ctest'in garip davranışı

Aug 19 2020

SO'da yeniyim. Aşağıdaki işlemleri yaptığım basit bir birim test kodum var:

  1. mysqrtkütüphaneyi kullanarak sayının karekökünü hesaplamak .
  2. Karekök çıktısını kullanarak, bu sonucu aynı sayı ile ekleyin ve sonucu görüntüleyin.

Kodu çalıştırdığımda CTEST_PARALLEL_LEVEL = 1tüm test durumlarım geçiyor.

Ancak bunu CTEST_PARALLEL_LEVEL = 8yaptığımda, test durumlarım her çalıştırmada sabit olmayan bazı girdiler için bir süre başarısız oluyor.

TÜM sonuçların% 99'u geçiyor, ancak% 1'i başarısız oluyor.

Hata:

mysqrt.o: file not recognized: File truncated

Rm * .o kullanarak nesne dosyasını açıkça sildim, ancak yine de bu hata birkaç çalıştırmadan sonra geliyor.

Bu hatanın neden geldiğinden emin değilim CTEST_PARALLEL_LEVEL = 8

Ben benim bağlama am CMakeListsadece yığın taşması eksperi olarak bu 3 kontrol ederek sorunu anlayabiliriz CMakeLists.txtdosyaları.

NOT: Yığın taşma yönergelerine göre, sorunun daha büyük olmasını önlemek için kaynak kodumu sqrt ve toplama işlevini eklemiyorum .

Klasör yapım:

SAMPLE_TEST

├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cpp
└── unit_test
    ├── CMakeLists.txt
    └── step2
        ├── CMakeLists.txt
        ├── execute.cpp
        └── tutorial.cpp

ÖRNEK TEST

CMakeLists.txt

cmake_minimum_required(VERSION 3.1)
project(Tutorial)
ENABLE_TESTING()    
add_subdirectory(MathFunctions)
add_subdirectory(unit_test)

MathFunctions klasörü

CMakeLists.txt

add_library(MathFunctions mysqrt.cpp)
set(REF_FILES mysqrt.cpp)
add_definitions(-Wall -Wextra -pedantic -std=c++11)
add_custom_target(build_reference_library
      DEPENDS sqrtlib
      COMMENT "Generating sqrtlib")
ADD_LIBRARY(sqrtlib OBJECT ${REF_FILES})

unit_test klasörü

CMakeLists.txt

set(REF_MATHLIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../MathFunctions)

macro(GENERATION file input)
  set(ip_generator ctest_input_${input}) add_executable(${ip_generator}
    ${file} $<TARGET_OBJECTS:sqrtlib>
    )

  target_compile_options(${ip_generator} PUBLIC -Wall -Wextra -g -std=c++11 -DCTEST_INPUT=${input})


  target_link_libraries(${ip_generator} PUBLIC dl pthread ) target_include_directories(${ip_generator} PUBLIC
    ${REF_MATHLIB_DIR} ) set(INPUT_FILE0 ip0_${input}.y)
  set(INPUT_FILE0_TXT ip0_${input}.txt) add_custom_command( OUTPUT ${INPUT_FILE0}  ${INPUT_FILE0_TXT} COMMAND ${ip_generator} > ${INPUT_FILE0_TXT} MAIN_DEPENDENCY ${sqrtlib}
    COMMENT "Generating output files of for testcase")
  
  add_custom_target(gen_input_${input} DEPENDS ${INPUT_FILE0}
    COMMENT "Generated output files")

endmacro() 

####################

macro(EXECUTE file input)
  get_filename_component(main_base_name ${file} NAME_WE) set(main_base_name_mangled ${main_base_name}_${input}) set(exe_generator ctest_ref_${input})

  add_executable(${exe_generator} ${file}
    $<TARGET_OBJECTS:sqrtlib> ) target_compile_options(${exe_generator} PUBLIC
    -Wall -Wextra -g -std=c++11 
    -DCTEST_INPUT=${input}) target_link_libraries(${exe_generator} PUBLIC
    dl pthread
    )

  target_include_directories(${exe_generator} PUBLIC ${REF_MATHLIB_DIR}
    )

  set(INPUT_FILE0 ip0_${input}.y) set(EXE_FILE0 exeadd_${input}.y)
  set(EXE_FILE_TXT exeadd_${input}.txt) add_custom_command( OUTPUT ${EXE_FILE0} ${EXE_FILE_TXT} COMMAND ${exe_generator}  > ${EXE_FILE_TXT} MAIN_DEPENDENCY ${INPUT_FILE0} ${sqrtlib} COMMENT "Generating output files of for testcase") add_custom_target(gen_execute_${input}
    DEPENDS ${EXE_FILE0} COMMENT "Generated output files") # add test to simulate add_test(NAME ctest_execute_${input}
      COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}
                               --target gen_execute_${input}) #add_dependencies(execute_${main_base_name_mangled}   
  #gen_input)

endmacro() 

#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#
# add test directories
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

set(TEST_DIRECTORIES
    step2
   )

foreach(dir ${TEST_DIRECTORIES}) add_subdirectory(${dir})
endforeach()

step2 klasörü

CMakeLists.txt

set(UT_IPGEN_FILES tutorial.cpp)
set(UT_EXECUTE_FILES execute.cpp)

set(input_integer_range 1 4 9 16 25 36 49 64 81 100 121 144 )

foreach(ip_integer ${input_integer_range}) GENERATION(${UT_IPGEN_FILES} ${ip_integer}) EXECUTE(${UT_EXECUTE_FILES} ${ip_integer})
endforeach(ip_integer)

Sonuç: 1. Çalıştırma:

      Start  1: ctest_execute_1
      Start  2: ctest_execute_4
      Start  3: ctest_execute_9
      Start  4: ctest_execute_16
      Start  5: ctest_execute_25
      Start  6: ctest_execute_36
      Start  7: ctest_execute_49
      Start  8: ctest_execute_64
 1/12 Test  #4: ctest_execute_16 .................***Failed    1.14 sec
 2/12 Test  #6: ctest_execute_36 .................   Passed    1.27 sec
 3/12 Test  #7: ctest_execute_49 .................   Passed    1.32 sec
 4/12 Test  #8: ctest_execute_64 .................   Passed    1.32 sec
      Start  9: ctest_execute_81
      Start 10: ctest_execute_100
      Start 11: ctest_execute_121
      Start 12: ctest_execute_144
 5/12 Test  #1: ctest_execute_1 ..................   Passed    1.33 sec
 6/12 Test  #2: ctest_execute_4 ..................   Passed    1.33 sec
 7/12 Test  #3: ctest_execute_9 ..................   Passed    1.33 sec
 8/12 Test  #5: ctest_execute_25 .................   Passed    1.33 sec
 9/12 Test #10: ctest_execute_100 ................   Passed    0.54 sec
10/12 Test #11: ctest_execute_121 ................   Passed    0.55 sec
11/12 Test  #9: ctest_execute_81 .................   Passed    0.55 sec
12/12 Test #12: ctest_execute_144 ................   Passed    0.55 sec
92% tests passed, 1 tests failed out of 12

Total Test time (real) =   1.88 sec

The following tests FAILED:
      4 - ctest_execute_16 (Failed)

2. Çalışma:

      Start  1: ctest_execute_1
      Start  2: ctest_execute_4
      Start  3: ctest_execute_9
      Start  4: ctest_execute_16
      Start  5: ctest_execute_25
      Start  6: ctest_execute_36
      Start  7: ctest_execute_49
      Start  8: ctest_execute_64
 1/12 Test  #6: ctest_execute_36 .................   Passed    1.31 sec
 2/12 Test  #7: ctest_execute_49 .................   Passed    1.36 sec
 3/12 Test  #8: ctest_execute_64 .................   Passed    1.36 sec
      Start  9: ctest_execute_81
      Start 10: ctest_execute_100
      Start 11: ctest_execute_121
 4/12 Test  #1: ctest_execute_1 ..................   Passed    1.37 sec
 5/12 Test  #2: ctest_execute_4 ..................   Passed    1.37 sec
 6/12 Test  #3: ctest_execute_9 ..................   Passed    1.36 sec
 7/12 Test  #4: ctest_execute_16 .................   Passed    1.36 sec
 8/12 Test  #5: ctest_execute_25 .................   Passed    1.37 sec
      Start 12: ctest_execute_144
 9/12 Test #11: ctest_execute_121 ................   Passed    0.50 sec
10/12 Test #10: ctest_execute_100 ................   Passed    0.51 sec
11/12 Test  #9: ctest_execute_81 .................   Passed    0.51 sec
12/12 Test #12: ctest_execute_144 ................   Passed    0.34 sec

100% tests passed, 0 tests failed out of 12

Total Test time (real) =   2.01 sec

Yanıtlar

Tsyvarev Aug 20 2020 at 13:51

Testleriniz yürütülüyor

COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ...

makeprojenin derleme dizininde etkin bir şekilde çalışan (veya kullandığınız derleme aracı).

Ama eşzamanlı çağırmaları arasında makeaynı dizinde doğru çalışması garanti asla. Bu nedenle testleri paralel olarak çalıştırdığınızda ( CTEST_PARALLEL_LEVELdeğişken ayarlandığında) garip hatalar alıyorsunuz .

Örneğin, tüm bu testler aynı nesne dosyasını oluşturmaya çalışıyor mysqrt.ove bu oluşturma kesinlikle iş parçacığı güvenli değil .

Koşarak

make sqrtlib

önce

ctest

Testler çalıştırıldığında nesne dosyasının zaten oluşturulmuş olduğundan emin olabilirsiniz ve testler onu yeniden oluşturmaya çalışmayacaktır. Ancak paralel testlerde yine de başka çatışmalar yaşayabilirsiniz.


Bu, test sırasında gerçekte neyi kontrol etmek istediğinize bağlıdır, ancak genellikle bir test , bazı programların veya kitaplıkların davranışını kontrol eder ve o programın bir derlemesini (derlemesini) kontrol etmeyi amaçlamaz. Bu nedenle derleme (oluşturma) komutları testten önce gerçekleştirilir .

Genellikle test için bu iş akışını takip etmek (uygulamak) uygundur:

# Configure the project
cmake <source-directory>
# Build the project.
# It builds both program/library intended, and the tests themselves.
make
# run tests
ctest <params>

Bu durumda bir test aşağıdaki tanıma sahip olabilir:

add_test(NAME ctest_execute_${input} COMMAND ${exe_generator})

(Testin çıktısını otomatik olarak kontrol etmek istemediğiniz sürece, bu çıktıyı dosyaya yeniden yönlendirerek açıkça kaydetmenize gerek yoktur. ctestTestin çıktısını kendi başına toplar, böylece gerekirse okuyabilirsiniz).