Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Xcodeのカバレッジ計測ではなぜブランチカバレッジが取れないのだろうか?

Daiki Katayama
September 06, 2019

 Xcodeのカバレッジ計測ではなぜブランチカバレッジが取れないのだろうか?

Daiki Katayama

September 06, 2019
Tweet

More Decks by Daiki Katayama

Other Decks in Programming

Transcript

  1. 9DPEFͷΧόϨοδܭଌͰ͸
    ͳͥϒϥϯνΧόϨοδ͕
    औΕͳ͍ͷͩΖ͏͔ʁ
    J04%$
    LBSJBE
    1

    View Slide

  2. ࣗݾ঺հ
    • kariad / @kariad_uu
    • ยࢁ େथ
    • ΦΠγοΫεɾϥɾେ஍גࣜձࣾ
    • ςετ / ઃܭ / ໊औ͞ͳ
    2
    ARIAͷ੟஍

    View Slide

  3. ΞδΣϯμ
    • ίʔυΧόϨοδʹ͍ͭͯ
    • XcodeͰͷίʔυΧόϨοδܭଌͱදࣔ
    • XcodeͰͷίʔυΧόϨοδܭଌͷ࢓૊Έ
    • ·ͱΊ
    3

    View Slide

  4. ίʔυΧόϨοδʹ͍ͭͯ
    4

    View Slide

  5. ίʔυΧόϨοδͱ͸
    • ιʔείʔυ͕ͲΕ͚ͩ໢ཏ͞Ε͔ͨͷׂ߹
    • ԿΛ৚݅ʹ໢ཏ཰ΛݟΔ͔ෳ਺ͷ؍఺͕͋
    Δ
    5

    View Slide

  6. • C0(εςʔτϝϯτΧόϨοδ)

    ໋ྩจ໢ཏɺ໋ྩจ͕ͲΕ͚ͩ໢ཏ͞Ε
    ͔ͨ
    • C1(ϒϥϯνΧόϨοδ)

    ෼ذ໢ཏɺ෼ذ͕ͲΕ͚ͩ໢ཏ͞Ε͔ͨ
    • C2(σΟγδϣϯΧόϨοδ)

    ৚݅໢ཏɺ৚͕݅ͲΕ͚ͩ໢ཏ͞Ε͔ͨ
    6

    View Slide

  7. 9DPEFͰͷ
    ίʔυΧόϨοδܭଌ
    7

    View Slide

  8. 8
    ςετΛ࣮ߦͨ͠Β…

    View Slide

  9. ͱͯ΋؆୯ʂ
    9

    View Slide

  10. ؆୯ʹऔΕΔ͚Ͳʜ
    • ͲͷछྨͷΧόϨοδΛऔΔ͔બ୒Ͱ͖ͳ͍
    • ͦ΋ͦ΋ͲΜͳ৚݅ͰΧόϨοδऔͬͯΔʁ
    10

    View Slide

  11. 9DPEFͷ
    ΧόϨοδܭଌͱදࣔͷ࣮ଶ
    11

    View Slide

  12. • ·ͣ͸ԿΛ৚݅ͱͨ͠ΧόϨοδΛදࣔ
    ͍ͯ͠Δ͔
    12

    View Slide

  13. • ࢀߟʹͳΔͷ͸WWDC 2018ͷ

    What’s New in Testing


    https://developer.apple.com/videos/play/
    wwdc2018/403/
    13

    View Slide

  14. • xccovͷ঺հ෦෼Ͱ໌֬ʹ

    Line coverage percentͱݴ͍ͬͯΔ
    • xccovͷ঺հͰ͸͋Δ͕ɺҧ͏΋ͷΛදࣔ
    ͍ͤͯ͞Δͱ΋ߟ͑ͮΒ͍
    14

    View Slide

  15. YDDPWͱ͸
    • Apple͕࡞ͬͨΧόϨοδΛਓʹ΋ಡΈ΍͢
    ͘දࣔͤ͞Δπʔϧ
    • JSONͰͷग़ྗ΋Ͱ͖Δ
    15

    View Slide

  16. ΧόϨοδͷݩσʔλ
    • xccovͰ࢖͏ιʔε͸Build/Logs/Test഑Լͷ
    16

    View Slide

  17. YDDPWΛ࢖࣮ͬͯࡍʹ
    ݟͯΈΔ
    xcrun xccov view action.xccovreport
    ΧόϨοδͷ֓ཁΛݟͯΈΔ
    17

    View Slide

  18. /Users/daiki/workspace/sandbox/MVP_ConnpassEventSearch/MVP_ConnpassEventSearch/
    MVP_ConnpassEventSearch/AppDelegate.swift
    48.15% (13/27)
    MVP_ConnpassEventSearch.AppDelegate.application(_: __C.UIApplication,
    didFinishLaunchingWithOptions: Swift.OptionalAny>>) -> Swift.Bool
    100.00% (10/10)
    MVP_ConnpassEventSearch.AppDelegate.applicationWillResignActive(__C.UIApplication) -> ()
    0.00% (0/4)
    MVP_ConnpassEventSearch.AppDelegate.applicationDidEnterBackground(__C.UIApplication) -> ()
    0.00% (0/4)
    MVP_ConnpassEventSearch.AppDelegate.applicationWillEnterForeground(__C.UIApplication) -> ()
    0.00% (0/3)
    MVP_ConnpassEventSearch.AppDelegate.applicationDidBecomeActive(__C.UIApplication) -> ()
    100.00% (3/3)
    MVP_ConnpassEventSearch.AppDelegate.applicationWillTerminate(__C.UIApplication) -> ()
    18

    View Slide

  19. MVP_ConnpassEventSearch.AppDelegate.applicatio
    nWillEnterForeground(__C.UIApplication) -> ()
    0.00% (0/3)
    ίϝϯτ΋ؚΊͯ3ߦ
    ΧόϨοδ͸Xcode্ͷදࣔͱҰக͢Δ
    19

    View Slide

  20. 9DPEFͰදࣔ͞Ε͍ͯΔ
    ΧόϨοδ͸ߦΛج४ʹܭଌͨ͠
    -JOFDPWFSBHF
    20

    View Slide

  21. • Line coverageͱ͍͏͜ͱ͸Θ͔ͬͨ
    • ଞͷΧόϨοδ͸औΕͳ͍ͷ͔ʁ
    21

    View Slide

  22. 9DPEFͷ
    ΧόϨοδܭଌͷ࢓૊Έ͔Β
    ݟ͍ͯ͘
    22

    View Slide

  23. ͦ΋ͦ΋ΧόϨοδ
    Ͳ͏΍ͬͯऔͬͯΔͷʁ
    • ώϯτ͸υΩϡϝϯτʹ
    • https://developer.apple.com/library/archive/
    documentation/DeveloperTools/Conceptual/
    testing_with_xcode/chapters/07-
    code_coverage.html
    23

    View Slide

  24. $PEFDPWFSBHFJO9DPEFJTB
    UFTUJOHPQUJPOTVQQPSUFECZ
    --7.
    24

    View Slide

  25. 9DPEF
    --7.ͷ
    ΧόϨοδܭଌͷ࢓૊Έ
    25

    View Slide

  26. --7.ͷΧόϨοδܭଌ
    • Source-based Code Coverage
    • SanitizerCoverage
    • gcov
    26

    View Slide

  27. --7.ͷΧόϨοδܭଌ
    • Source-based Code Coverage
    • SanitizerCoverage
    • gcov
    27

    View Slide

  28. 4PVSDFCBTFE
    $PEF$PWFSBHF
    • AST΍ϓϦϓϩηοα৘ใΛ௚઀ૢ࡞͢Δ͜
    ͱ͔ΒSource-basedͱݺ͹ΕΔ
    • ؆୯ʹ݁ՌΛࢹ֮Խ͢Δ͜ͱ·ͰՄೳ
    • ͓ͦΒ͘࠷΋ελϯμʔυͳ΋ͷ
    28

    View Slide

  29. ࣮ࡍʹ4XJGUͷ
    4PVSDFCBTFE$PEF$PWFSBHF
    ΛऔͬͯΈΔ
    29

    View Slide

  30. 1. ΧόϨοδܭଌΛ༗ޮʹͯ͠ίϯύΠϧ
    2. ੜ੒͞ΕͨϓϩάϥϜΛ࣮ߦ
    3. ΧόϨοδϨϙʔτͷੜ੒
    खॱ
    30

    View Slide

  31. main.swift
    let number = 10
    if number % 2 == 0 {
    print("ۮ਺")
    }
    ୯७ͳϓϩάϥϜͰܭଌͯ͠ΈΔ
    31

    View Slide

  32. ΧόϨοδܭଌΛ
    ༗ޮʹͯ͠ίϯύΠϧ
    xcrun swiftc -profile-generate
    -profile-coverage-mapping main.swift
    ϓϩάϥϜ
    32

    View Slide

  33. ੜ੒͞Εͨ
    ϓϩάϥϜΛ࣮ߦ
    ϓϩάϥϜ
    EFGBVMUQSPGSBX
    ΧόϨοδ৘ใͷੜσʔλ
    33

    View Slide

  34. ΧόϨοδϨϙʔτΛੜ੒
    xcrun llvm-profdata merge -o
    testprof.profdata default.profraw
    UFTUQSPGQSPGEBUB
    profrawϑΝΠϧ͸ͦͷ··ͩͱϨϙʔτΛग़ྗͰ͖Δ
    ܗࣜͰ͸ͳ͘ΠϯσοΫεΛ͚ͭΔඞཁ͕͋Δ
    testprof͸ࣗ෼Ͱ໋໊
    34

    View Slide

  35. UFTUQSPGQSPGEBUB
    ࠷ऴతͳΧόϨοδ৘ใ͕ೖͬͨϑΝΠϧ

    ͜ͷঢ়ଶͩͱ·ͩਓ͕ಡΊΔঢ়ଶͰ͸ͳ͍
    llvm-covΛ࢖ͬͯΧόϨοδ৘ใͷදࣔ΍JSONͰ
    ͷग़ྗΛߦ͏͜ͱ͕Ͱ͖Δ
    35

    View Slide

  36. xcrun llvm-cov show ./main
    -instr-profile=sample.profdata main.swift
    ߦʹରԠͨ͠ΧόϨοδ৘ใ
    36

    View Slide

  37. ccMFUOVNCFS*OU
    cc
    ccJGOVNCFS\
    ccQSJOU ۮ਺

    cc^
    37

    View Slide

  38. • llvm-cov͸ҙ֎ͱߴػೳ
    • htmlͰͷग़ྗ΍ϨϙʔτܗࣜͰͷग़ྗʹ
    ΋ରԠ
    • ܭଌର৅ʹਖ਼نදݱΛ༻͍ͯಛఆͷϑΝ
    ΠϧΛؚΊͳ͍͜ͱ΋
    • ࢖͍ํ࠷ޙʹ͚ͭ·ͨ͠
    38

    View Slide

  39. xcrun llvm-cov export ./main -instr-
    profile=testprof.profdata main.swift
    JSONͷΧόϨοδ৘ใ

    ௕͗ͯ͢εϥΠυʹશͯ͸ࡌΓ·ͤΜͰͨ͠
    39

    View Slide

  40. "totals": {
    "lines": {
    "count": 3,
    "covered": 3,
    "percent": 100
    },
    "functions": {
    "count": 2,
    "covered": 2,
    "percent": 100
    },
    "instantiations": {
    "count": 2,
    "covered": 2,
    "percent": 100
    },
    "regions": {
    "count": 4,
    "covered": 4,
    "notcovered": 0,
    "percent": 100
    }
    }
    llvm-covͰग़ྗͨ͠

    JSONͷҰ෦
    • lines
    • functions
    • Instantiations
    • regions
    40

    View Slide

  41. • ࣮͸Source-based Code Coverage͸4छྨͷ
    ΧόϨοδΛܭଌ͢Δ͜ͱ͕Ͱ͖Δ
    41

    View Slide

  42. -JOFDPWFSBHF
    • ߦͰݟͨΧόϨοδ(ίϝϯτؚΉ)
    • σϑΥϧτͷઃఆ͸͜Ε
    • ࣮ࡍʹLine਺Ͱ෇͖߹ΘͤͯΈΔͱ׬શʹҰ
    க͢ΔͨΊXcodeͰද͍ࣔͯ͠Δͷ͸͜Ε
    42

    View Slide

  43. 'VODUJPODPWFSBHF
    *OTUBOUJBUJPODPWFSBHF
    • ؔ਺ͷݺͼग़͠ճ਺
    • ΠϯελϯεԽͷճ਺
    43

    View Slide

  44. 3FHJPODPWFSBHF
    • ίʔυͷྖҬͰଌΔΧόϨοδ
    • ࡾ߲ԋࢉࢠͳͲ΋1ߦͰ͸ͳ͘ෳ਺ͱΈͳ͢
    • Source-based Code CoverageͰ͸Ұ൪ཻ౓͕ࡉ
    ͔͍
    44

    View Slide

  45. let result = 10 % 2 == 0 ? true : false
    1ߦ͚ͩͷ؆୯ͳίʔυͷΧόϨοδΛݟͯΈΔ
    45

    View Slide

  46. Line coverage
    Region coverage
    46

    View Slide

  47. ɾಉ͡Line coverage͕͋ΔͷͰXcodeͰ͸
    Source-based Code CoverageΛར༻ͯͦ͠͏
    ɾXcode্දࣔ͞Ε͍ͯΔΧόϨοδ͸
    Line coverage͕ͩSource-based Code Coverage
    ͱ͍͏͜ͱͳΒܭଌࣗମ͸4छྨߦΘΕ͍ͯ
    Δ͸ͣ
    47

    View Slide

  48. ͱݴ͏͜ͱ͸Region coverage΋औಘͰ͖Δ
    ͷͰ͸…
    48

    View Slide

  49. BuildϑΥϧμΛআ͘ͱ…
    49

    View Slide

  50. • Coverage.profdataϑΝΠϧ͕ଘࡏ͢Δ
    • *.profdataܗࣜͳͷͰllvm-covΛ࢖ͬͯݟΔ
    ͜ͱ͕Ͱ͖Δ
    50

    View Slide

  51. xcrun llvm-cov report ../../Products/Debug-iphonesimulator/
    {ProductName}.app/{ProductName} -instr-profile=Coverage.profdata
    51

    View Slide

  52. • Line coverageΑΓࡉ͔͍Region coverageΛ
    ؆୯ʹΈΔ͜ͱ͕Ͱ͖Δ
    • ͔͠͠ຊ౰ʹগ͚͔ͩ͠͠ࡉ͔͘ͳ͍͔
    ΋͠Εͳ͍
    52

    View Slide

  53. • && ΍ || ͱ͍ͬͨ৚݅ʹ͍ͭͯ͸

    Line coverageͰݕग़Ͱ͖Δ
    53

    View Slide

  54. struct Foo {
    func bar() {
    let number = 10
    if number % 2 == 0
    || number == 10
    {
    print("ۮ਺Ͱ10")
    }
    }
    }
    54

    View Slide

  55. struct Foo {
    func bar() {
    let number = 10
    if number % 2 == 0
    || number == 10
    {
    print("ۮ਺Ͱ10")
    }
    }
    }
    struct Coverage {
    func hhoge() {
    let number = 10
    if number % 2 == 0
    || number == 10
    {
    print("ۮ਺Ͱ10")
    }
    }
    }
    55

    View Slide

  56. ϝιου͚ͩͰΈΔͱ100%͕ͩ

    implicit closureͱͯ͠දࣔ͞Ε͓ͯΓɺ

    ϑΝΠϧ୯ҐͰ͸໢ཏͰ͖͍ͯͳ͍͜ͱ͕
    Θ͔Δ
    56

    View Slide

  57. public static func || (lhs: Bool, rhs:
    @autoclosure () throws -> Bool) rethrows
    -> Bool {
    return lhs ? true : try rhs()
    }
    Swiftͷ࣮૷ͱͯ͠&&΍||ͷӈล͸closureͱͯ͠
    ॲཧ͞ΕΔ
    57

    View Slide

  58. • closure͕ผͰܭଌ͞Ε͍ͯΔ
    • ͦͷཧ༝Λ஌ΔͨΊʹSource-based Code
    Coverage͕ͲͷΑ͏ʹऔಘ͞Ε͍ͯΔ͔
    Λ؆୯ʹݟͯΈΔ
    58

    View Slide

  59. • Source-based Code Coverage͸LLVM͕ఏڙ
    ͢ΔCode Coverage Mapping Formatͱ͍͏
    ΋ͷΛར༻ͯ͠ܭଌ͍ͯ͠Δ
    • ΦϓγϣϯΛ͚ͭͯίϯύΠϧͨ͠ࡍʹ
    Ϛοϐϯά༻ͷσʔλ͕ຒΊࠐ·ΕΔ
    59

    View Slide

  60. • ͜ͷϚοϐϯάϑΥʔϚοτ͸LLVMΛ
    όοΫΤϯυͱͯ࣋ͭ͠ϑϩϯτΤϯυ
    ͷϢχόʔαϧϑΥʔϚοτΛ໨ࢦͯ͠
    ͍Δ
    • LLVMΛόοΫΤϯυʹ΋ͭશͯͷϑϩϯ
    τΤϯυͰڞ௨ͯ͠औಘͰ͖ΔΧόϨο
    δ
    60

    View Slide

  61. • LLVMͷυΩϡϝϯτʹCoverage Mapping
    Formatʹ͍ͭͯઆ໌ͨ͠΋ͷ͕ଘࡏ͢Δ

    https://llvm.org/docs/
    CoverageMappingFormat.html
    • ͦΕʹΑΔͱϑϩϯτΤϯυ͕LLVM IRΛ
    ੜ੒͢ΔࡍʹຒΊࠐ·ΕΔ
    61

    View Slide

  62. • ͪͳΈʹSwiftcͰ͸IRGen.cppͷ

    performIRGeneration()


    GenDecl.cppͷ

    IRGenerator::emitGlobalTopLevel()


    GenCoverageͷ

    IRGenModule::emitCoverageMapping()
    • llvm/ProfileData/Coverage/CoverageMappingWriter.h
    62

    View Slide

  63. ͱ͍͏Θ͚Ͱ--7.*3Λ
    ݟ͍ͯ͘
    63

    View Slide

  64. xcrun swiftc -emit-ir -profile-generate -profile-coverage-mapping
    Coverage/main.swift
    • -emit-irΛΦϓγϣϯͱͯ͠౉͢͜ͱͰ
    LLVM IRΛग़ྗ͢Δ͜ͱ͕Ͱ͖Δ
    • ΧόϨοδΛ༗ޮʹͯ͠LLVM IRΛग़ྗ
    64

    View Slide

  65. ܭଌΦϑ ܭଌΦϯ
    ࠩ෼͕ͨ͘͞Μ͋Δͷ͕Θ͔Δ
    65

    View Slide

  66. @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" = linkonce hidden global [2 x i64] zeroinitializer,
    section "__DATA,__llvm_prf_cnts", align 8
    @"__profd_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF" = linkonce hidden global { i64, i64, i64*, i8*, i8*,
    i32, [2 x i16] } { i64 1740746221156547191, i64 0, i64* getelementptr inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF", i32 0, i32 0), i8* bitcast (void ()*
    @"$S4Hoge3FooV3baryyF" to i8*), i8* null, i32 2, [2 x i16] zeroinitializer }, section
    "__DATA,__llvm_prf_data,regular,live_support", align 8
    @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1" = linkonce hidden global [1 x i64] zeroinitializer,
    section "__DATA,__llvm_prf_cnts", align 8
    @"__profd_Coverage/Coverage.swift:__ntd_Foo_line:1:1" = linkonce hidden global { i64, i64, i64*, i8*, i8*, i32,
    [2 x i16] } { i64 -7581103708217037269, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1", i32 0, i32 0), i8* bitcast (void ()*
    @"$S4Hoge3FooVACycfC" to i8*), i8* null, i32 1, [2 x i16] zeroinitializer }, section
    "__DATA,__llvm_prf_data,regular,live_support", align 8
    @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_" = linkonce hidden global [1 x i64]
    zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
    @"__profd_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_" = linkonce hidden global { i64, i64,
    i64*, i8*, i8*, i32, [2 x i16] } { i64 3556985279047318519, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x
    i64]* @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i32 0, i32 0), i8* bitcast (void
    ()* @"$S4Hoge3FooV3baryyF" to i8*), i8* null, i32 1, [2 x i16] zeroinitializer }, section
    "__DATA,__llvm_prf_data,regular,live_support", align 8
    ϔομʔ෦෼ͷҰ෦ʹ஫໨
    66

    View Slide

  67. @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF"
    @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1"
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_"
    ͜ͷ3ͭͷάϩʔόϧม਺ʹ஫໨͢Δ
    ͜ͷ··ͩͱΘ͔Βͳ͍ͷͰσϚϯάϧͯ͠ΈΔ
    67

    View Slide

  68. @"__profc_Coverage/Coverage.swift:Hoge.Foo.bar() -> ()
    @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1"
    @"__profc_Coverage/Coverage.swift:implicit closure #1 :
    @autoclosure () throws -> Swift.Bool in Hoge.Foo.bar() -> ()
    @"__profc_Coverage/Coverage.swift:$S4Hoge3FooV3baryyF"
    @"__profc_Coverage/Coverage.swift:__ntd_Foo_line:1:1"
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_"
    68

    View Slide

  69. • ͜ΕΒͷάϩʔόϧม਺͸Χ΢ϯλͱ
    Ϛοϐϯά৘ใΛอଘ͍ͯ͠Δ΋ͷ
    69

    View Slide

  70. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    70

    View Slide

  71. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    71

    View Slide

  72. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    ઌ΄ͲσϚϯάϧͨ͠ΒҎԼʹͳͬͨ΋ͷ
    @"__profc_Coverage/Coverage.swift:Hoge.Foo.bar() -> ()
    72

    View Slide

  73. ͲΜͳॲཧΛ͍ͯ͠Δ͔
    งғؾͰ
    ݟ͍ͯ͘
    73

    View Slide

  74. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    ͔͜͜ΒFoo.bar()ͷελʔτ
    74

    View Slide

  75. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    άϩʔόϧม਺(഑ྻ)͔ΒཁૉΛऔΓग़ͯ͠ɺ
    ϨδελpgocountೖΕ͍ͯΔ
    75

    View Slide

  76. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    pgocountͱ1ΛՃࢉͯ͠Ϩδελ0ʹೖΕ͍ͯΔ
    76

    View Slide

  77. define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    define hidden swiftcc void
    @"$S4Hoge3FooV3baryyF"() #0 {
    entry:
    %pgocount = load i64, i64* getelementptr
    inbounds ([2 x i64], [2 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyF", i64 0, i64 0)
    %0 = add i64 %pgocount, 1
    store i64 %0, i64* getelementptr inbounds
    ([2 x i64], [2 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyF", i64 0,
    i64 0)
    br label %1
    ܭࢉ݁ՌͷϨδελ0Λάϩʔόϧม਺ʹอଘ
    77

    View Slide

  78. • ͜ͷॲཧʹΑͬͯͲͷؔ਺ͷͲͷϒϩο
    ΫΛ௨ա͔ͨ͠ͷճ਺Χ΢ϯτ͕ߦΘΕ
    ͍ͯΔ
    78

    View Slide

  79. ; :3: ; preds = %2
    br i1 true, label %4, label %7
    ͨͩͷ෼ذ
    79

    View Slide

  80. ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    80

    View Slide

  81. ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    81

    View Slide

  82. ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    ઌ΄ͲσϚϯάϧͨ͠ΒҎԼʹͳͬͨ΋ͷ
    @"__profc_Coverage/Coverage.swift:implicit closure #1 :
    @autoclosure () throws -> Swift.Bool in Hoge.Foo.bar() -> ()
    82

    View Slide

  83. ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    ; :7: ; preds = %3
    %pgocount1 = load i64, i64* getelementptr
    inbounds ([1 x i64], [1 x i64]*
    @"__profc_Coverage/Coverage.swift:
    $S4Hoge3FooV3baryyFSbyKXKfu_", i64 0, i64 0)
    %8 = add i64 %pgocount1, 1
    store i64 %8, i64* getelementptr inbounds ([1 x
    i64], [1 x i64]* @"__profc_Coverage/
    Coverage.swift:$S4Hoge3FooV3baryyFSbyKXKfu_", i64
    0, i64 0)
    br label %9
    ͦͷଞͷ෦෼ʹ͍ͭͯ͸ઌ΄Ͳͱಉ͡Ճࢉॲཧ
    83

    View Slide

  84. • ͦ΋ͦ΋Χ΢ϯτ͢Δࡍʹผͷؔ਺ͱ͠
    ͯΧ΢ϯτ͞Ε͍ͯͨ
    • ͳͷͰϑΝΠϧ୯ҐͰ͸ݟ͔ͭΔ͕ɺϝ
    ιου୯ҐͰ͸ݟ͔ͭΒͳ͔ͬͨ
    84

    View Slide

  85. • ͱ͍͏͜ͱ͔ΒLine coverageͰ΋&&΍||ͷΧό
    ϨοδΛݟΔ͜ͱ͸Ͱ͖Δ
    • ࠓͷॴࢲ͕ؾ͕෇͍ͨRegion coverageͰ͔͠ݟͭ
    ͚ΒΕͳ͍΋ͷ͸3߲ԋࢉࢠͱ1ߦʹ·ͱΊͯॻ
    ͍ͨifจ͘Β͍…
    • ͦΕͰ΋Line coverageΑΓ͸ࡉ͔͘औΕΔͷͰ
    Region coverageΛ࢖ͬͯܭଌͯ͠΋͍͍͔΋͠Ε
    ͳ͍
    85

    View Slide

  86. ϒϥϯνΧόϨοδ
    Ͳ͍ͬͨ͜
    • XcodeͰར༻͍ͯ͠ΔΧόϨοδܭଌ͕
    Source-based Code CoverageͷͨΊɺXcode্
    ͷϏϧυ͔ΒϒϥϯνΧόϨοδΛऔΔ͜
    ͱ͸Ͱ͖ͳ͍
    86

    View Slide

  87. --7.ͷΧόϨοδܭଌ
    • Source-based Code Coverage
    • SanitizerCoverage
    • gcov
    87

    View Slide

  88. --7.ͷΧόϨοδܭଌ
    • Source-based Code Coverage

    → Θ͔ͬͨ
    • SanitizerCoverage
    • gcov 

    → swiftcʹ࣮૷͞Ε͍ͯͳͦ͞͏
    88

    View Slide

  89. 4BOJUJ[FS$PWFSBHF
    • LLVMͱswiftcͰऔΕΔ΋͏ҰͭͷΧόϨοδ
    • Τοδͱݺ͹ΕΔΧόϨοδΛऔಘͰ͖Δ
    89

    View Slide

  90. Τοδͱ͸
    if 1 == 1 {
    print("hogehoge")
    }
    90

    View Slide

  91. A
    B
    C
    ௨ৗ͸3ͭͷϒϩοΫ
    91

    View Slide

  92. A
    B
    C
    D
    edgeΛ༗ޮʹ͢Δͱ
    Dͱ͍͏μϛʔϒϩοΫ͕ੜ੒͞ΕΔ
    92

    View Slide

  93. ͔ͤͬ͘ͳͷͰ
    --7.*3΋ݟΑ͏
    93

    View Slide

  94. ; :2: ; preds = %1
    br i1 true, label %3, label %._crit_edge
    ._crit_edge: ; preds = %2
    call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64
    add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4)
    to i32*))
    call void asm sideeffect "", ""()
    br label %46
    ; :3: ; preds = %2
    Ұ෦ൈਮ
    94

    View Slide

  95. ; :2: ; preds = %1
    br i1 true, label %3, label %._crit_edge
    ._crit_edge: ; preds = %2
    call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64
    add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4)
    to i32*))
    call void asm sideeffect "", ""()
    br label %46
    ; :3: ; preds = %2
    ; :2: ; preds = %1
    br i1 true, label %3, label %._crit_edge
    ._crit_edge: ; preds = %2
    call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64
    add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4)
    to i32*))
    call void asm sideeffect "", ""()
    br label %46
    ; :3: ; preds = %2
    ෼ذઌʹcrit_edgeͱ͍͏΋ͷ͕ଘࡏ͢Δ
    95

    View Slide

  96. ; :2: ; preds = %1
    br i1 true, label %3, label %._crit_edge
    ._crit_edge: ; preds = %2
    call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64
    add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4)
    to i32*))
    call void asm sideeffect "", ""()
    br label %46
    ; :3: ; preds = %2
    ; :2: ; preds = %1
    br i1 true, label %3, label %._crit_edge
    ._crit_edge: ; preds = %2
    call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64
    add (i64 ptrtoint ([5 x i32]* @__sancov_gen_ to i64), i64 4)
    to i32*))
    call void asm sideeffect "", ""()
    br label %46
    ; :3: ; preds = %2
    ຒΊࠐ·Εͨؔ਺ΛݺΜͰ͍Δ
    96

    View Slide

  97. • μϛʔϒϩοΫͱ͸LLVM IRͰຊདྷԿ΋ͳ
    ͍෼ذઌʹൃੜ͢ΔϒϩοΫ
    97

    View Slide

  98. ΧόϨοδΛݟͯΈΔ
    98

    View Slide

  99. • SanitizerCoverage͸ग़ྗ͕໘౗
    • sancovͱ͍͏toolΛ࢖͏ඞཁ͕͋Δ
    • LLVMΛผ్DL͠ͳ͍ͱೖ͍ͬͯͳ͍
    99

    View Slide

  100. xcrun swiftc -sanitize=address -sanitize-coverage=edge
    Coverage/main.swift
    ASAN_OPTIONS=coverage=1 ./main;wc -c *.sancov
    main.****.sancov
    100

    View Slide

  101. sancov -print-coverage-stats main.52871.sancov ./main
    all-edges: 5
    cov-edges: 5
    all-functions: 4
    cov-functions: 4
    ૯edge਺ͱΧόʔͨ͠edge਺͕ݟΕΔ
    101

    View Slide

  102. sancov -symbolize main.52871.sancov ./main > main.symcov
    HTMLͰݟΔͨΊʹ͸γϯϘϥΠζͯ͠
    ͋͛Δඞཁ͕͋Δ
    102

    View Slide

  103. {
    "covered-points" : ["100000b2d", "100000c22", "100000c9f", "100000ccf", "100000d1c"],
    "binary-hash" : "5CCB31D0F47A427284B9EE58B2C89557D382CD0B",
    "point-symbol-info" : {
    "" : {
    "$ss5print_9separator10terminatoryypd_S2StFfA0_" : {
    "100000c9f" : "0:0"
    },
    "$ss5print_9separator10terminatoryypd_S2StFfA1_" : {
    "100000ccf" : "0:0"
    },
    "asan.module_dtor" : {
    "100000d1c" : "0:0"
    },
    "main" : {
    "100000b2d" : "0:0",
    "100000c22" : "0:0"
    }
    }
    }
    }
    103

    View Slide

  104. • llvm/tools/sancov/ ഑Լʹ͋Δ

    coverage-report-server.pyͰ

    HTTPαʔόΛىಈ͢Δ
    • coverage-report-server.py΋brewͰΠϯε
    τʔϧͨ͠LLVMʹ͸ແ͔ͬͨͷͰผ్DL
    104

    View Slide

  105. python3 coverage-report-server.py --symcov ~/workspace/Coverage/
    main2.symcov --srcpath ~/workspace/Coverage/
    ຊདྷ͸ϑΝΠϧ໊͕දࣔ͞ΕΔ͸͕ͣͩɺinvalidʹͳͬͯ͠·
    ͍ݟΕͳ͔ͬͨ(sancov͕Linux͔͠αϙʔτ͍ͯ͠ͳ͍ͷͰͦΕ
    ͕ݪҼ͔΋͠Εͳ͍)
    105

    View Slide

  106. • edgeΧόϨοδΛҰԠݟΕΔ
    • ͔͠͠edgeΧόϨοδ͸෼ذͷ਺Λج४
    ʹݟ͍ͯΔͱ͍͏Θ͚Ͱ͸ͳ͍ͷͰϒϥ
    ϯνΧόϨοδͱ͸গ͠ҟͳΔ
    106

    View Slide

  107. ϒϥϯνΧόϨοδ͸
    औΕΔͷ͔
    107

    View Slide

  108. औΕ·ͤΜʂʂ
    108

    View Slide

  109. • edgeͱϒϥϯν͸ҟͳΔ΋ͷͳͷͰݫີ
    ʹϒϥϯνΧόϨοδΛऔΔ࢓૊Έ͸ແ
    ͔ͬͨ
    • ͦ΋ͦ΋ݱঢ়ͷ΋εςʔτϝϯτΧό
    ϨοδͰ͸ແ͔ͬͨ(Line coverage)
    109

    View Slide

  110. ँࡑ
    110

    View Slide

  111. ϓϩϙʔβϧͷҰ෦
    • ҰํͰίʔυΧόϨοδʹ͸͍͔ͭ͘छྨ͕
    ͋ΓɺXcodeͰ͸ͦͷҰͭͰ͋Δεςʔτϝ
    ϯτΧόϨοδ͔͠ܭଌͰ͖ͳ͍ͱ͍͏͜ͱ
    Λ͝ଘ஌Ͱ͠ΐ͏͔ɻ
    111

    View Slide

  112. ϓϩϙʔβϧͷҰ෦
    • ҰํͰίʔυΧόϨοδʹ͸͍͔ͭ͘छྨ͕
    ͋ΓɺXcodeͰ͸ͦͷҰͭͰ͋Δεςʔτϝ
    ϯτΧόϨοδ͔͠ܭଌͰ͖ͳ͍ͱ͍͏͜ͱ
    Λ͝ଘ஌Ͱ͠ΐ͏͔ɻ
    112
    XcodeͰݟΕΔͷ͸
    Line coverageͰ͢ʂ

    View Slide

  113. • ͨͩ͠Region coverageͱ͍͏Line coverage
    ΑΓࡉ͔͍΋ͷ͕؆୯ʹΈΔ͜ͱ͕Ͱ͖
    Δ
    • %ͰͳΒ͹ҰԠedge coverage΋ݟΔ͜ͱ͸
    Ͱ͖Δ
    113

    View Slide

  114. ͦΜͳίʔυΧόϨοδΛ
    Ͳ͏ͯ͠ͱΓ͍͔ͨ
    114

    View Slide

  115. • ΧόϨοδ͸Ͳ͕͜ॻ͚͍ͯͳ͍͔Λݟ
    Δ͜ͱ͕Ͱ͖Δπʔϧ
    • Ͳ͕͜ॻ͚͍ͯͳ͍͔෼͔Ε͹௥Ճ͢Δ
    ͜ͱ΋Ͱ͖Δ
    • (ͨͩ͠ॻ͚͍ͯͳ͍ͱ͜ΖΛશͯॻ͘΂
    ͖͔Ͳ͏͔͸ผͷ࿩)
    115

    View Slide

  116. • ࡉ͔͘νΣοΫͯ͘͠ΕΔ΄Ͳؾ͕෇͔
    ͳ͔ͬͨͱ͜Ζʹؾ͕͚ͭΔ
    • ͋͘·Ͱ΋ิॿπʔϧͱͯ͠࢖͏
    116

    View Slide

  117. ·ͱΊ
    • XcodeͰ͸Line coverage͕දࣔ͞Ε͍ͯΔ
    • গ͠ࡉ͔͍Region coverage΋औΕΔ
    • ϒϥϯνΧόϨοδ͸औΕͳ͍͕ɺedgeͰͷˋͳ
    Β(ҰԠ)ݟΕΔ
    • ΧόϨοδΛ্खʹ׆༻ͯ͠ྑ͍ςετϥΠϑΛ
    117

    View Slide

  118. ࢀߟࢿྉ
    • Code Coverage - Apple Developer

    https://developer.apple.com/library/archive/documentation/
    DeveloperTools/Conceptual/testing_with_xcode/chapters/07-
    code_coverage.html
    • Source-based Code Coverage - Clang 10 documentation

    https://clang.llvm.org/docs/
    SourceBasedCodeCoverage.html#exporting-coverage-data
    • LLVM Code Coverage Mapping Format - LLVM 10 documentation

    https://llvm.org/docs/CoverageMappingFormat.html
    118

    View Slide

  119. • llvm-cov - emit coverage information - LLVM 10
    documentation

    https://llvm.org/docs/CommandGuide/llvm-cov.html
    • SwiftίϯύΠϥͷΞʔΩςΫνϟ

    https://qiita.com/rintaro/items/3ad640e3938207218c20
    • https://github.com/apple/swift
    • SwiftίϯύΠϥͷManglingͷษڧํ๏

    https://qiita.com/omochimetaru/items/
    60b0d50146e0abbc9b7b
    119

    View Slide

  120. • LLVM Language Reference Manual - LLVM 10
    documentation

    https://llvm.org/docs/LangRef.html
    • AddressSanitizerFlags

    https://github.com/google/sanitizers/wiki/
    AddressSanitizerFlags
    120

    View Slide

  121. ͓·͚
    121

    View Slide

  122. YDDPWͷ࢖͍ํ
    122

    View Slide

  123. xcrun xccov view *.xccovreport
    ϑΝΠϧຖʹԿˋͱ͍ͬͨΞϓϦέʔ
    γϣϯશମͷΧόϨοδͷ֓ཁΛݟΔ͜
    ͱ͕Ͱ͖Δ
    123

    View Slide

  124. xcrun xccov view *.xccovarchive/ --file *.swift
    ಛఆͷϑΝΠϧͷԿߦ໨͕Կճ࣮ߦ͞Ε͔ͨ
    ͷৄࡉΛݟΔ͜ͱ͕Ͱ͖Δ
    ·ͨϑΝΠϧΛࢦఆ͢Δࡍʹ͸

    xcrun xccov view —file-list *.xccovarchive/

    Ͱ֤ϑΝΠϧͷύεΛ֬ೝͰ͖Δ
    124

    View Slide

  125. MMWNDPWͷ࢖͍ํ
    125

    View Slide

  126. • https://llvm.org/docs/CommandGuide/llvm-
    cov.html
    • جຊ͜͜ʹॻ͍ͯ͋Γ·͢
    126

    View Slide

  127. • 3छྨͷग़ྗํ๏
    • show / report / export
    • show - ͲͷҐஔ͕௨ա͍ͯ͠ͳ͍͔͕ιʔε
    ίʔυͱରԠ͚ͮΒΕͯݟΕΔ
    • report - ֤ϑΝΠϧͷLine / Function / Region
    coverageͷsummary͕ҰཡͰݟΕΔ
    • export - JSON΍lcovܗࣜͰग़ྗ͕Ͱ͖Δ
    127

    View Slide

  128. • xcrun llvm-cov -show -format html -show-
    regions -instr-profile=**.profdata

    ͰHTMLͰιʔείʔυͱରԠͨ͠Region
    coverageΛݟΔ͜ͱ͕Ͱ͖Δ
    128

    View Slide

  129. 129

    View Slide

  130. • xcrun llvm-cov report -ignore-filename-
    regex=[pattern] -instr-profile=*.profdata
    • ਖ਼نදݱͰܭଌ͠ͳ͍ϑΝΠϧΛࢦఆͰ
    ͖Δ
    • -ignore-filename-regex=.*ViewController.swift

    ͰViewControllerΛআ֎͢ΔͳΜͯ͜ͱ΋
    130

    View Slide

  131. ͋Γ͕ͱ͏͍͟͝·ͨ͠
    131
    Twitter: @kariad_uu

    View Slide