diff --git a/cmd/merge.go b/cmd/merge.go new file mode 100644 index 0000000..50435e7 --- /dev/null +++ b/cmd/merge.go @@ -0,0 +1,72 @@ +/* + Copyright 2020 Qiniu Cloud (qiniu.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cmd + +import ( + "log" + + "github.com/spf13/cobra" + "golang.org/x/tools/cover" + "k8s.io/test-infra/gopherage/pkg/cov" + "k8s.io/test-infra/gopherage/pkg/util" +) + +var mergeCmd = &cobra.Command{ + Use: "merge [files...]", + Short: "Merge multiple coherent Go coverage files into a single file.", + Long: `merge will merge multiple Go coverage files into a single coverage file. +merge requires that the files are 'coherent', meaning that if they both contain references to the +same paths, then the contents of those source files were identical for the binary that generated +each file. +`, + Run: func(cmd *cobra.Command, args []string) { + run(cmd, args) + }, +} + +var outputMergeProfile string + +func init() { + mergeCmd.Flags().StringVarP(&outputMergeProfile, "output", "o", "mergeprofile.cov", "output file") + + rootCmd.AddCommand(mergeCmd) +} + +func run(cmd *cobra.Command, args []string) { + if len(args) == 0 { + log.Fatalln("Expected at least one coverage file.") + } + + profiles := make([][]*cover.Profile, len(args)) + for _, path := range args { + profile, err := util.LoadProfile(path) + if err != nil { + log.Fatalf("failed to open %s: %v", path, err) + } + profiles = append(profiles, profile) + } + + merged, err := cov.MergeMultipleProfiles(profiles) + if err != nil { + log.Fatalf("failed to merge files: %v", err) + } + + err = util.DumpProfile(outputMergeProfile, merged) + if err != nil { + log.Fatalln(err) + } +} diff --git a/pkg/cover/client.go b/pkg/cover/client.go index 7bdbb44..6567d8b 100644 --- a/pkg/cover/client.go +++ b/pkg/cover/client.go @@ -20,12 +20,13 @@ import ( "fmt" "io" "io/ioutil" - "log" "net" "net/http" "net/url" "strconv" "strings" + + log "github.com/sirupsen/logrus" ) // Action provides methods to contact with the covered service under test diff --git a/tests/merge.bats b/tests/merge.bats new file mode 100755 index 0000000..f8cb0cd --- /dev/null +++ b/tests/merge.bats @@ -0,0 +1,60 @@ +#!/usr/bin/env bats +# Copyright 2020 Qiniu Cloud (七牛云) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load util.sh + +setup_file() { + # run centered server + goc server 3>&- & + GOC_PID=$! + sleep 2 + goc init + + info "goc server started" +} + +teardown_file() { + kill -9 $GOC_PID +} + +setup() { + goc init +} + +@test "test goc merge command" { + cd samples/merge_profile_samples + + wait_profile_backend "merge1" & + profile_pid=$! + + # merge two profiles with same binary + run gocc merge a.voc b.voc --debug --debugcisyncfile ci-sync.bak; + info merge1 output: $output + [ "$status" -eq 0 ] + run cat mergeprofile.cov + [[ "$output" == *"qiniu.com/kodo/apiserver/server/main.go:32.49,33.13 1 60"* ]] + [[ "$output" == *"qiniu.com/kodo/apiserver/server/main.go:42.49,43.13 1 2"* ]] + + # merge two profiles from two binaries, but has some source code in common + run gocc merge a.voc c.voc --debug --debugcisyncfile ci-sync.bak; + info merge1 output: $output + [ "$status" -eq 0 ] + run cat mergeprofile.cov + [[ "$output" == *"qiniu.com/kodo/apiserver/server/main.go:32.49,33.13 1 60"* ]] + [[ "$output" == *"qiniu.com/kodo/apiserver/server/main.go:42.49,43.13 1 0"* ]] + [[ "$output" == *"qiniu.com/kodo/apiserver/server/wala.go:42.49,43.13 1 0"* ]] + + wait $profile_pid +} diff --git a/tests/samples/merge_profile_samples/a.voc b/tests/samples/merge_profile_samples/a.voc new file mode 100644 index 0000000..5c8b06e --- /dev/null +++ b/tests/samples/merge_profile_samples/a.voc @@ -0,0 +1,3 @@ +mode: atomic +qiniu.com/kodo/apiserver/server/main.go:32.49,33.13 1 30 +qiniu.com/kodo/apiserver/server/main.go:42.49,43.13 1 0 \ No newline at end of file diff --git a/tests/samples/merge_profile_samples/b.voc b/tests/samples/merge_profile_samples/b.voc new file mode 100644 index 0000000..c361181 --- /dev/null +++ b/tests/samples/merge_profile_samples/b.voc @@ -0,0 +1,3 @@ +mode: atomic +qiniu.com/kodo/apiserver/server/main.go:32.49,33.13 1 30 +qiniu.com/kodo/apiserver/server/main.go:42.49,43.13 1 2 \ No newline at end of file diff --git a/tests/samples/merge_profile_samples/c.voc b/tests/samples/merge_profile_samples/c.voc new file mode 100644 index 0000000..348ef73 --- /dev/null +++ b/tests/samples/merge_profile_samples/c.voc @@ -0,0 +1,4 @@ +mode: atomic +qiniu.com/kodo/apiserver/server/main.go:32.49,33.13 1 30 +qiniu.com/kodo/apiserver/server/main.go:42.49,43.13 1 0 +qiniu.com/kodo/apiserver/server/wala.go:42.49,43.13 1 0 \ No newline at end of file