summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pelletier/go-toml/v2/ci.sh
blob: d916c5f237f1da2a836f4bd81992ef40409a0d8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#!/usr/bin/env bash


stderr() {
    echo "$@" 1>&2
}

usage() {
    b=$(basename "$0")
    echo $b: ERROR: "$@" 1>&2

    cat 1>&2 <<EOF

DESCRIPTION

    $(basename "$0") is the script to run continuous integration commands for
    go-toml on unix.

    Requires Go and Git to be available in the PATH. Expects to be ran from the
    root of go-toml's Git repository.

USAGE

    $b COMMAND [OPTIONS...]

COMMANDS

benchmark [OPTIONS...] [BRANCH]

    Run benchmarks.

    ARGUMENTS

        BRANCH Optional. Defines which Git branch to use when running
               benchmarks.

    OPTIONS

        -d      Compare benchmarks of HEAD with BRANCH using benchstats. In
                this form the BRANCH argument is required.

        -a      Compare benchmarks of HEAD against go-toml v1 and
                BurntSushi/toml.

        -html   When used with -a, emits the output as HTML, ready to be
                embedded in the README.

coverage [OPTIONS...] [BRANCH]

    Generates code coverage.

    ARGUMENTS

        BRANCH  Optional. Defines which Git branch to use when reporting
                coverage. Defaults to HEAD.

    OPTIONS

        -d      Compare coverage of HEAD with the one of BRANCH. In this form,
                the BRANCH argument is required. Exit code is non-zero when
                coverage percentage decreased.
EOF
    exit 1
}

cover() {
    branch="${1}"
    dir="$(mktemp -d)"

    stderr "Executing coverage for ${branch} at ${dir}"

    if [ "${branch}" = "HEAD" ]; then
	    cp -r . "${dir}/"
    else
	    git worktree add "$dir" "$branch"
    fi

    pushd "$dir"
    go test -covermode=atomic  -coverpkg=./... -coverprofile=coverage.out.tmp ./...
    cat coverage.out.tmp | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
    go tool cover -func=coverage.out
    popd

    if [ "${branch}" != "HEAD" ]; then
	    git worktree remove --force "$dir"
    fi
}

coverage() {
    case "$1" in
	-d)
	    shift
	    target="${1?Need to provide a target branch argument}"

	    output_dir="$(mktemp -d)"
	    target_out="${output_dir}/target.txt"
	    head_out="${output_dir}/head.txt"
	    
	    cover "${target}" > "${target_out}"
	    cover "HEAD" > "${head_out}"

	    cat "${target_out}"
	    cat "${head_out}"

	    echo ""

	    target_pct="$(tail -n2 ${target_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%.*/\1/')"
	    head_pct="$(tail -n2 ${head_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%/\1/')"
	    echo "Results: ${target} ${target_pct}% HEAD ${head_pct}%"

	    delta_pct=$(echo "$head_pct - $target_pct" | bc -l)
	    echo "Delta: ${delta_pct}"

	    if [[ $delta_pct = \-* ]]; then
		    echo "Regression!";

            target_diff="${output_dir}/target.diff.txt"
            head_diff="${output_dir}/head.diff.txt"
            cat "${target_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${target_diff}"
            cat "${head_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${head_diff}"

            diff --side-by-side --suppress-common-lines "${target_diff}" "${head_diff}"
		    return 1
	    fi
	    return 0
	    ;;
    esac

    cover "${1-HEAD}"
}

bench() {
    branch="${1}"
    out="${2}"
    replace="${3}"
    dir="$(mktemp -d)"

    stderr "Executing benchmark for ${branch} at ${dir}"

    if [ "${branch}" = "HEAD" ]; then
    	cp -r . "${dir}/"
    else
	    git worktree add "$dir" "$branch"
    fi

    pushd "$dir"

    if [ "${replace}" != "" ]; then
        find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2|${replace}|g" {} \;
        go get "${replace}"
    fi

    export GOMAXPROCS=2
    nice -n -19 taskset --cpu-list 0,1 go test '-bench=^Benchmark(Un)?[mM]arshal' -count=5 -run=Nothing ./... | tee "${out}"
    popd

    if [ "${branch}" != "HEAD" ]; then
	    git worktree remove --force "$dir"
    fi
}

fmktemp() {
    if mktemp --version|grep GNU >/dev/null; then
        mktemp --suffix=-$1;
    else
        mktemp -t $1;
    fi
}

benchstathtml() {
python3 - $1 <<'EOF'
import sys

lines = []
stop = False

with open(sys.argv[1]) as f:
    for line in f.readlines():
        line = line.strip()
        if line == "":
            stop = True
        if not stop:
            lines.append(line.split(','))

results = []
for line in reversed(lines[1:]):
    v2 = float(line[1])
    results.append([
        line[0].replace("-32", ""),
        "%.1fx" % (float(line[3])/v2),  # v1
        "%.1fx" % (float(line[5])/v2),  # bs
    ])
# move geomean to the end
results.append(results[0])
del results[0]


def printtable(data):
    print("""
<table>
    <thead>
        <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
    </thead>
    <tbody>""")

    for r in data:
        print("        <tr><td>{}</td><td>{}</td><td>{}</td></tr>".format(*r))

    print("""     </tbody>
</table>""")


def match(x):
    return "ReferenceFile" in x[0] or "HugoFrontMatter" in x[0]

above = [x for x in results if match(x)]
below = [x for x in results if not match(x)]

printtable(above)
print("<details><summary>See more</summary>")
print("""<p>The table above has the results of the most common use-cases. The table below
contains the results of all benchmarks, including unrealistic ones. It is
provided for completeness.</p>""")
printtable(below)
print('<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>')
print("</details>")

EOF
}

benchmark() {
    case "$1" in
    -d)
        shift
     	target="${1?Need to provide a target branch argument}"

        old=`fmktemp ${target}`
        bench "${target}" "${old}"

        new=`fmktemp HEAD`
        bench HEAD "${new}"

        benchstat "${old}" "${new}"
        return 0
        ;;
    -a)
        shift

        v2stats=`fmktemp go-toml-v2`
        bench HEAD "${v2stats}" "github.com/pelletier/go-toml/v2"
        v1stats=`fmktemp go-toml-v1`
        bench HEAD "${v1stats}" "github.com/pelletier/go-toml"
        bsstats=`fmktemp bs-toml`
        bench HEAD "${bsstats}" "github.com/BurntSushi/toml"

        cp "${v2stats}" go-toml-v2.txt
        cp "${v1stats}" go-toml-v1.txt
        cp "${bsstats}" bs-toml.txt

        if [ "$1" = "-html" ]; then
            tmpcsv=`fmktemp csv`
            benchstat -csv -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt > $tmpcsv
            benchstathtml $tmpcsv
        else
            benchstat -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt
        fi

        rm -f go-toml-v2.txt go-toml-v1.txt bs-toml.txt
        return $?
    esac

    bench "${1-HEAD}" `mktemp`
}

case "$1" in
    coverage) shift; coverage $@;;
    benchmark) shift; benchmark $@;;
    *) usage "bad argument $1";;
esac