diff --git a/cmd/buildFileCoverage/buildFileCoverage.go b/cmd/buildFileCoverage/buildFileCoverage.go index 1e91cc0..107dfee 100644 --- a/cmd/buildFileCoverage/buildFileCoverage.go +++ b/cmd/buildFileCoverage/buildFileCoverage.go @@ -62,14 +62,14 @@ func main() { log.SetReportCaller(true) log.Infof("Begin creating metadata structures by reading %s...", covFile) - MetaMap, err = pp.ReadCovMetadata(covFile) + MetaMap, _, err = pp.ReadCovMetadata(covFile) if err != nil { log.Fatal(err) } FileCovCounts = make(map[string]int) - sampleCovMap, err := pp.ReadFileToCovMap(covFile) + sampleCovMap, _, err := pp.ReadFileToCovMap(covFile) if err != nil { log.Fatal(err) } diff --git a/cmd/correlate/correlate.go b/cmd/correlate/correlate.go index 5fc0de8..6d50399 100644 --- a/cmd/correlate/correlate.go +++ b/cmd/correlate/correlate.go @@ -73,67 +73,68 @@ var SiteCats map[string]CloudflareCategoryEntry var ExcludeVector []bool -//var DirectoriesOfInterest = []string{ -// "third_party/blink", -// "android_webview", -// "apps", -// "ash", -// "base", -// "build", -// "cc", -// "chrome", -// "chromecast", -// "chromeos", -// "cloud_print", -// "codelabs", -// "components", -// "content", -// "courgette", -// "crypto", -// "dbus", -// "device", -// "docs", -// "extensions", -// "fuchsia", -// "gin", -// "google_apis", -// "google_update", -// "gpu", -// "headless", -// "infra", -// "ios", -// "ipc", -// "jingle", -// "media", -// "mojo", -// "native_client", -// "native_client_sdk", -// "net", -// "out", -// "pdf", -// "ppapi", -// "printing", -// "remoting", -// "rlz", -// "sandbox", -// "services", -// "skia", -// "sql", -// "storage", -// "styleguide", -// "testing", -// "third_party", -// "tools", -// "ui", -// "url", -// "v8", -// "weblayer", -//} - var DirectoriesOfInterest = []string{ + "third_party/blink", + "android_webview", + "apps", + "ash", + "base", + "build", + "cc", + "chrome", + "chromecast", + "chromeos", + "cloud_print", + "codelabs", + "components", + "content", + "courgette", + "crypto", + "dbus", + "device", + "docs", + "extensions", + "fuchsia", + "gin", + "google_apis", + "google_update", + "gpu", + "headless", + "infra", + "ios", + "ipc", + "jingle", + "media", + "mojo", + "native_client", + "native_client_sdk", + "net", + "out", + "pdf", + "ppapi", + "printing", + "remoting", + "rlz", + "sandbox", + "services", + "skia", + "sql", + "storage", + "styleguide", + "testing", + "third_party", + "tools", + "ui", + "url", + "v8", + "weblayer", "net/websockets", } +//var DirectoriesOfInterest = []string{ +// "net/websockets", +//} + func main() { var covFile string var resultsPath string @@ -147,7 +148,7 @@ func main() { flag.StringVar(&outfile, "out", "file_coverage.csv", "Path to output file csv") flag.StringVar(&excludeBVFile, "excludeBV", "", - "BV file to exlcude set regions from analysis") + "BV file to exclude set regions from analysis") flag.Parse() @@ -164,18 +165,23 @@ func main() { log.SetReportCaller(true) log.Infof("Begin creating metadata structures by reading %s...", covFile) - MetaMap, err = pp.ReadCovMetadata(covFile) + var metaProps pp.CovMapProperties + MetaMap, metaProps, err = pp.ReadCovMetadata(covFile) if err != nil { log.Fatal(err) } + log.Infof("MetaMap Files: %d, Funcs: %d, Regions: %d", metaProps.NumFiles, metaProps.NumFunctions, metaProps.NumRegions) + FileCovCounts = make(map[string]int) - sampleCovMap, err := pp.ReadFileToCovMap(covFile) + sampleCovMap, props, err := pp.ReadFileToCovMap(covFile) if err != nil { log.Fatal(err) } + log.Infof("CovMap Files: %d, Funcs: %d, Regions: %d", props.NumFiles, props.NumFunctions, props.NumRegions) + files := 0 functions := 0 regions := 0 @@ -203,24 +209,41 @@ func main() { } } BVIndexToCodeRegionMap = pp.GenerateBVIndexToCodeRegionMap(Structure, MetaMap) + log.Infof("BVIndexToCodeRegionMap Length: %d", len(BVIndexToCodeRegionMap)) // Build FilenameToBVIndices Map FilenameToBVIndices = make(map[string]BVRange) currentIndex := 0 start := 0 end := 0 - for k, v := range Structure { + totalRegions := 0 + + fileNames := make([]string, 0) + for fileName := range Structure { + fileNames = append(fileNames, fileName) + } + sort.Strings(fileNames) + + for _, fileName := range fileNames { start = currentIndex - for _, numBlocks := range v { - currentIndex += numBlocks + funcNames := make([]string, 0) + for funcName := range Structure[fileName] { + funcNames = append(funcNames, funcName) + } + + for _, funcName := range funcNames { + currentIndex += Structure[fileName][funcName] } end = currentIndex - FilenameToBVIndices[k] = BVRange{ + FilenameToBVIndices[fileName] = BVRange{ Start: start, End: end, } + totalRegions += end - start } + log.Infof("Total Files, Regions for FilenameToBVIndices: %d, %d", len(FilenameToBVIndices), totalRegions) + FileCoverage = make(map[string][]float64) log.Infof("Finished parsing metadata") @@ -344,9 +367,9 @@ func worker(taskChan chan Task, resultChan chan Result, wg *sync.WaitGroup) { indices := FilenameToBVIndices[fileName] fileCov := 0 for i := indices.Start; i < indices.End; i++ { - //if ExcludeVector[i] { - // continue - //} + if ExcludeVector[i] { + continue + } for _, dir := range DirectoriesOfInterest { if isDirMap[dir] { totalBlocksPerDir[dir] += 1 diff --git a/cmd/generateExclude/generateExclude.go b/cmd/generateExclude/generateExclude.go new file mode 100644 index 0000000..3c58f00 --- /dev/null +++ b/cmd/generateExclude/generateExclude.go @@ -0,0 +1,162 @@ +package main + +import ( + "encoding/csv" + "flag" + log "github.com/sirupsen/logrus" + pp "github.com/teamnsrg/profparse" + "io" + "math" + "os" + "strconv" + "sync" +) + +type Task struct { + Path string +} + +var CompleteCounter int + +var Accumulator []bool +var AccumLock sync.Mutex + +/* +File,Function,Region Number,Functions in File,Regions in File,Regions in Function,Times File Covered,Percent Times File Covered,Times Function Covered,Percent Times Function Covered,Times Region Covered,Percent Times Region Covered +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor11AddObserverEPNS0_8ObserverE,0,15,55,1,3999,1.0000,3999,1.0000,3999,1.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor13NotifyAppStopERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE,1,15,55,2,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor13NotifyAppStopERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE,2,15,55,2,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor14NotifyAppStartERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE,3,15,55,2,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor14NotifyAppStartERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE,4,15,55,2,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor14RemoveObserverEPNS0_8ObserverE,5,15,55,1,3999,1.0000,3998,0.9997,3998,0.9997 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor16OnAppWindowShownEPN10extensions9AppWindowEb,6,15,55,8,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor16OnAppWindowShownEPN10extensions9AppWindowEb,7,15,55,8,3999,1.0000,0,0.0000,0,0.0000 +../../apps/app_lifetime_monitor.cc,_ZN4apps18AppLifetimeMonitor16OnAppWindowShownEPN10extensions9AppWindowEb,8,15,55,8,3999,1.0000,0,0.0000,0,0.0000 +*/ + +var COVERED_ALWAYS_OR_NEVER_EXCLUDE = []string{ + "output/vanilla_region_coverage.csv", + "output/gremlins_region_coverage.csv", + // "output/headless_region_coverage.csv", +} + +var COVERED_EVEN_ONCE_EXCLUDE = []string{ + "aboutblank_region_coverage.csv", +} + +const float64EqualityThreshold = 1e-6 + +func almostEqual(a, b float64) bool { + return math.Abs(a-b) <= float64EqualityThreshold +} + +func main() { + var outfile string + var covFile string + + flag.StringVar(&outfile, "out", "output/exclude_vector.bv", + "Path to output file csv") + flag.StringVar(&covFile, "coverage-file", "coverage.txt", + "Path to sample text coverage file for metadata generation") + flag.Parse() + + var err error + + sampleCovMap, _, err := pp.ReadFileToCovMap(covFile) + if err != nil { + log.Fatal(err) + } + + files := 0 + functions := 0 + regions := 0 + + Structure := pp.ConvertCovMapToStructure(sampleCovMap) + for _, v1 := range Structure { + files += 1 + for _, v2 := range v1 { + functions += 1 + regions += v2 + } + } + + alwaysSoFar := make([]bool, regions) + neverSoFar := make([]bool, regions) + for i, _ := range alwaysSoFar { + alwaysSoFar[i] = true + neverSoFar[i] = true + } + + for _, fileName := range COVERED_ALWAYS_OR_NEVER_EXCLUDE { + alwaysCovered, _ := pp.CountCoveredRegions(alwaysSoFar) + log.Infof("Always covered: %d", alwaysCovered) + neverCovered, _ := pp.CountCoveredRegions(neverSoFar) + log.Infof("Never covered: %d", neverCovered) + + alwaysSoFar, neverSoFar, err = getAlwaysAndNeverCoveredVector(alwaysSoFar, neverSoFar, fileName, regions) + if err != nil { + log.Fatal(err) + } + } + + excludeVector, totalExcluded, err := pp.CombineBVs([][]bool{ + alwaysSoFar, neverSoFar, + }) + + log.Infof("Total Excluded: %d", totalExcluded) + + pp.WriteFileFromBV(outfile, excludeVector) + alwaysCovered, _ := pp.CountCoveredRegions(alwaysSoFar) + log.Infof("Always covered: %d", alwaysCovered) + neverCovered, _ := pp.CountCoveredRegions(neverSoFar) + log.Infof("Never covered: %d", neverCovered) + + totalExcludedRegions, totalRegions := pp.CountCoveredRegions(excludeVector) + log.Infof("Excluding a total of %d out of %d regions", totalExcludedRegions, totalRegions) +} + +func getAlwaysAndNeverCoveredVector(alwaysSoFar []bool, neverSoFar []bool, regionCoverageFile string, numRegions int) ([]bool, []bool, error) { + f, err := os.Open(regionCoverageFile) + if err != nil { + return nil, nil, err + } + reader := csv.NewReader(f) + + header := true + + always := make([]bool, numRegions) + never := make([]bool, numRegions) + + for { + record, err := reader.Read() + if err == io.EOF { + break + } + if err != nil { + log.Fatal(err) + } + + if header { + header = false + continue + } + + regionNumber, err := strconv.Atoi(record[2]) + if err != nil { + log.Fatal(err) + } + + percentTimesRegionCovered, err := strconv.ParseFloat(record[11], 32) + if err != nil { + log.Fatal(err) + } + + isNeverCovered := almostEqual(percentTimesRegionCovered, 0.0) + isAlwaysCovered := almostEqual(percentTimesRegionCovered, 1.0) + + always[regionNumber] = alwaysSoFar[regionNumber] && isAlwaysCovered + never[regionNumber] = neverSoFar[regionNumber] && isNeverCovered + } + + return always, never, nil +} diff --git a/cmd/metadata_only/metadata_only.go b/cmd/metadata_only/metadata_only.go index 6d50399..3cd6721 100644 --- a/cmd/metadata_only/metadata_only.go +++ b/cmd/metadata_only/metadata_only.go @@ -57,17 +57,7 @@ type CloudflareCategoryEntry struct { Application CloudflareApplication `json:"application"` } -var MetaMap map[string]map[string][]pp.CodeRegion -var Structure map[string]map[string]int -var BVIndexToCodeRegionMap map[int]pp.CodeRegion -var FilenameToBVIndices map[string]BVRange var CompleteCounter int -var SortedFiles []string -var DenominatorFileCoverageMap map[string]int -var DenominatorTree map[string]int -var FileCoverage map[string][]float64 -var FileCovCounts map[string]int -var FileCovCountLock sync.Mutex var SiteCats map[string]CloudflareCategoryEntry @@ -141,8 +131,6 @@ func main() { var outfile string var excludeBVFile string - flag.StringVar(&covFile, "coverage-file", "coverage.txt", - "Path to sample text coverage file for metadata generation") flag.StringVar(&resultsPath, "results-path", "results", "Path to MIDA results for analysis") flag.StringVar(&outfile, "out", "file_coverage.csv", @@ -165,93 +153,7 @@ func main() { log.SetReportCaller(true) log.Infof("Begin creating metadata structures by reading %s...", covFile) - var metaProps pp.CovMapProperties - MetaMap, metaProps, err = pp.ReadCovMetadata(covFile) - if err != nil { - log.Fatal(err) - } - - log.Infof("MetaMap Files: %d, Funcs: %d, Regions: %d", metaProps.NumFiles, metaProps.NumFunctions, metaProps.NumRegions) - - FileCovCounts = make(map[string]int) - - sampleCovMap, props, err := pp.ReadFileToCovMap(covFile) - if err != nil { - log.Fatal(err) - } - - log.Infof("CovMap Files: %d, Funcs: %d, Regions: %d", props.NumFiles, props.NumFunctions, props.NumRegions) - - files := 0 - functions := 0 - regions := 0 - - sampleBV := pp.ConvertCovMapToBools(sampleCovMap) - - log.Info("Reading BV to exclude") - if excludeBVFile != "" { - ExcludeVector, err = pp.ReadBVFileToBV(excludeBVFile) - if err != nil { - log.Fatal(err) - } - log.Infof("Read exclude vector (length: %d)", len(ExcludeVector)) - } else { - ExcludeVector = make([]bool, len(sampleBV)) - log.Infof("Created empty exclude vector (length: %d)", len(ExcludeVector)) - } - - Structure = pp.ConvertCovMapToStructure(sampleCovMap) - for _, v1 := range Structure { - files += 1 - for _, v2 := range v1 { - functions += 1 - regions += v2 - } - } - BVIndexToCodeRegionMap = pp.GenerateBVIndexToCodeRegionMap(Structure, MetaMap) - log.Infof("BVIndexToCodeRegionMap Length: %d", len(BVIndexToCodeRegionMap)) - - // Build FilenameToBVIndices Map - FilenameToBVIndices = make(map[string]BVRange) - currentIndex := 0 - start := 0 - end := 0 - totalRegions := 0 - - fileNames := make([]string, 0) - for fileName := range Structure { - fileNames = append(fileNames, fileName) - } - sort.Strings(fileNames) - - for _, fileName := range fileNames { - start = currentIndex - funcNames := make([]string, 0) - for funcName := range Structure[fileName] { - funcNames = append(funcNames, funcName) - } - - for _, funcName := range funcNames { - currentIndex += Structure[fileName][funcName] - } - end = currentIndex - FilenameToBVIndices[fileName] = BVRange{ - Start: start, - End: end, - } - totalRegions += end - start - } - - log.Infof("Total Files, Regions for FilenameToBVIndices: %d, %d", len(FilenameToBVIndices), totalRegions) - - FileCoverage = make(map[string][]float64) - - log.Infof("Finished parsing metadata") - log.Infof(" - Total Files: %d", files) - log.Infof(" - Total Functions: %d", functions) - log.Infof(" - Total Code Regions: %d\n", regions) - - covPaths, err := pp.GetCovPathsMIDAResults(resultsPath, true) + covPaths, err := pp.GetPathsMidaResults(resultsPath, true) if err != nil { log.Fatal(err) } @@ -259,15 +161,9 @@ func main() { var resultsPaths []string for _, c := range covPaths { - resultsPaths = append(resultsPaths, strings.TrimSuffix(c, "coverage/coverage.bv")) + resultsPaths = append(resultsPaths, c) } - sort.Strings(covPaths) - SortedFiles = make([]string, 0) - for k := range Structure { - SortedFiles = append(SortedFiles, k) - } - sort.Strings(SortedFiles) taskChan := make(chan Task, 10000) resultsChan := make(chan Result, 10000) @@ -307,13 +203,7 @@ func worker(taskChan chan Task, resultChan chan Result, wg *sync.WaitGroup) { log.Infof("Processing task: %s", task.Path) pathsParts := strings.Split(task.Path, "/") - domain := pathsParts[len(pathsParts)-3] - - bv, err := pp.ReadBVFileToBV(path.Join(task.Path, "coverage", "coverage.bv")) - if err != nil { - log.Error(err) - continue - } + domain := pathsParts[len(pathsParts)-2] metadata, err := pp.LoadMidaMetadata(path.Join(task.Path, "metadata.json")) if err != nil { @@ -339,67 +229,6 @@ func worker(taskChan chan Task, resultChan chan Result, wg *sync.WaitGroup) { continue } - var blocksCovered int64 = 0 - var genBlocksCovered int64 = 0 - var srcBlocksCovered int64 = 0 - - totalBlocksPerDir := make(map[string]int64) - coveredBlocksPerDir := make(map[string]int64) - - for _, dir := range DirectoriesOfInterest { - totalBlocksPerDir[dir] = 0 - coveredBlocksPerDir[dir] = 0 - } - - for _, fileName := range SortedFiles { - isGen := strings.HasPrefix(fileName, "gen/") - isSrc := strings.HasPrefix(fileName, "../../") - - isDirMap := make(map[string]bool) - for _, dir := range DirectoriesOfInterest { - if strings.HasPrefix(fileName, "gen/"+dir) || strings.HasPrefix(fileName, "../../"+dir) { - isDirMap[dir] = true - } else { - isDirMap[dir] = false - } - } - - indices := FilenameToBVIndices[fileName] - fileCov := 0 - for i := indices.Start; i < indices.End; i++ { - if ExcludeVector[i] { - continue - } - for _, dir := range DirectoriesOfInterest { - if isDirMap[dir] { - totalBlocksPerDir[dir] += 1 - if bv[i] { - coveredBlocksPerDir[dir] += 1 - if isGen { - genBlocksCovered += 1 - } - if isSrc { - srcBlocksCovered += 1 - } - } - } - } - - if bv[i] { - fileCov += 1 - blocksCovered += 1 - } - } - - FileCovCountLock.Lock() - if _, ok := FileCoverage[fileName]; !ok { - FileCoverage[fileName] = make([]float64, 0) - } - FileCoverage[fileName] = append(FileCoverage[fileName], float64(fileCov)/float64(indices.End-indices.Start)) - - FileCovCountLock.Unlock() - } - resourceDir := path.Join(task.Path, "resources") dirSize, err := DirSize(resourceDir) if err != nil { @@ -429,18 +258,6 @@ func worker(taskChan chan Task, resultChan chan Result, wg *sync.WaitGroup) { r.Category = "UNKNOWN" } - r.TotalBlocksCovered = blocksCovered - r.GenBlocksCovered = genBlocksCovered - r.SrcBlocksCovered = srcBlocksCovered - r.DirBlocksCovered = coveredBlocksPerDir - - r.PercentDirBlocksCovered = make(map[string]float64) - for _, dir := range DirectoriesOfInterest { - r.PercentDirBlocksCovered[dir] = float64(r.DirBlocksCovered[dir]) / float64(totalBlocksPerDir[dir]) - log.Infof("Dir: %s, Covered: %d, Total: %d, Percent: %.02f", dir, - r.DirBlocksCovered[dir], totalBlocksPerDir[dir], float64(r.DirBlocksCovered[dir])/float64(totalBlocksPerDir[dir])) - } - resultChan <- r CompleteCounter += 1 @@ -468,14 +285,6 @@ func writer(resultChan chan Result, wwg *sync.WaitGroup, outfile string) { "Browser Open Time", "Total Resources", "Total Resource Bytes", - "Total Blocks Covered", - "Gen Blocks Covered", - "Src Blocks Covered", - } - - for _, dir := range DirectoriesOfInterest { - header = append(header, "RegionsCovered: "+dir) - header = append(header, "PercentCovered: "+dir) } writer.Write(header) @@ -491,14 +300,6 @@ func writer(resultChan chan Result, wwg *sync.WaitGroup, outfile string) { strconv.FormatFloat(result.BrowserOpenTime, 'f', 2, 64), strconv.Itoa(result.TotalResources), strconv.FormatInt(result.TotalResourceBytesDownloaded, 10), - strconv.FormatInt(result.TotalBlocksCovered, 10), - strconv.FormatInt(result.GenBlocksCovered, 10), - strconv.FormatInt(result.SrcBlocksCovered, 10), - } - - for _, dir := range DirectoriesOfInterest { - line = append(line, strconv.FormatInt(result.DirBlocksCovered[dir], 10)) - line = append(line, strconv.FormatFloat(result.PercentDirBlocksCovered[dir], 'f', 4, 64)) } writer.Write(line) diff --git a/cmd/regionCoverage/regionCoverage.go b/cmd/regionCoverage/regionCoverage.go index 85b51a2..6278727 100644 --- a/cmd/regionCoverage/regionCoverage.go +++ b/cmd/regionCoverage/regionCoverage.go @@ -74,7 +74,7 @@ func main() { // log.SetReportCaller(true) log.Infof("Begin creating metadata structures by reading %s...", covFile) - MetaMap, err = pp.ReadCovMetadata(covFile) + MetaMap, _, err = pp.ReadCovMetadata(covFile) if err != nil { log.Fatal(err) } @@ -82,7 +82,7 @@ func main() { FileCovCounts = make(map[string]int) FuncCovCounts = make(map[string]int) - sampleCovMap, err := pp.ReadFileToCovMap(covFile) + sampleCovMap, _, err := pp.ReadFileToCovMap(covFile) if err != nil { log.Fatal(err) } diff --git a/cmd/repeatCompare/repeatCompare.go b/cmd/repeatCompare/repeatCompare.go new file mode 100644 index 0000000..15ca76e --- /dev/null +++ b/cmd/repeatCompare/repeatCompare.go @@ -0,0 +1,298 @@ +package main + +import ( + "encoding/csv" + "flag" + log "github.com/sirupsen/logrus" + pp "github.com/teamnsrg/profparse" + "os" + "sort" + "strconv" + "sync" +) + +type Task struct { + Path string +} + +type Result struct { + Path string + FilesCovered int + FunctionsCovered int + RegionsCovered int +} + +type BVRange struct { + Start int //inclusive + End int // exclusive +} + +/** + * This analyzes region coverage across a results set.\ + * It produces two output files: one showing how many times each region was covered, + * and one showing how many regions each site visit covered. + */ + +var MetaMap map[string]map[string][]pp.CodeRegion +var Structure map[string]map[string]int +var BVIndexToCodeRegionMap map[int]pp.CodeRegion +var FilenameToBVIndices map[string]BVRange +var CompleteCounter int +var SortedFiles []string +var FileCoverage map[string][]float64 + +var FileCovCounts map[string]int +var FileCovCountLock sync.Mutex +var FuncCovCounts map[string]int +var FuncCovCountLock sync.Mutex + +var regionCoverage []int +var regionCoverageLock sync.Mutex + +func main() { + var covFile string + var resultsPath string + + flag.StringVar(&covFile, "coverage-file", "coverage.txt", + "Path to sample text coverage file for metadata generation") + flag.StringVar(&resultsPath, "results-path", "results", + "Path to MIDA results for analysis") + + flag.Parse() + + var err error + CompleteCounter = 0 + // log.SetReportCaller(true) + log.Infof("Begin creating metadata structures by reading %s...", covFile) + + MetaMap, _, err = pp.ReadCovMetadata(covFile) + if err != nil { + log.Fatal(err) + } + + FileCovCounts = make(map[string]int) + FuncCovCounts = make(map[string]int) + + sampleCovMap, _, err := pp.ReadFileToCovMap(covFile) + if err != nil { + log.Fatal(err) + } + + files := 0 + functions := 0 + regions := 0 + + Structure = pp.ConvertCovMapToStructure(sampleCovMap) + for _, v1 := range Structure { + files += 1 + for _, v2 := range v1 { + functions += 1 + regions += v2 + } + } + BVIndexToCodeRegionMap = pp.GenerateBVIndexToCodeRegionMap(Structure, MetaMap) + + // Build FilenameToBVIndices Map + FilenameToBVIndices = make(map[string]BVRange) + currentIndex := 0 + start := 0 + end := 0 + for k, v := range Structure { + start = currentIndex + for _, numBlocks := range v { + currentIndex += numBlocks + } + end = currentIndex + FilenameToBVIndices[k] = BVRange{ + Start: start, + End: end, + } + } + + FileCoverage = make(map[string][]float64) + + log.Infof("Finished parsing metadata") + log.Infof(" - Total Files: %d", files) + log.Infof(" - Total Functions: %d", functions) + log.Infof(" - Total Code Regions: %d\n", regions) + + covPaths, err := pp.GetCovPathsMIDAResults(resultsPath, false) + if err != nil { + log.Fatal(err) + } + + regionCoverage = make([]int, regions) + + sort.Strings(covPaths) + SortedFiles = make([]string, 0) + for k := range Structure { + SortedFiles = append(SortedFiles, k) + } + sort.Strings(SortedFiles) + + taskChan := make(chan Task, 10000) + resultChan := make(chan Result, 10000) + var wg sync.WaitGroup + var owg sync.WaitGroup + + owg.Add(1) + go writer(resultChan, &owg, crawlRegionCoverageOutfile) + + WORKERS := 28 + for i := 0; i < WORKERS; i++ { + wg.Add(1) + go worker(taskChan, resultChan, &wg) + } + + for _, path := range covPaths { + var t Task + t.Path = path + taskChan <- t + } + + close(taskChan) + wg.Wait() + close(resultChan) + owg.Wait() + + numTrials := len(covPaths) + log.Infof("numTrials: %s", numTrials) + + outfileName := outfile + + log.Info("Finishing...") + f, err := os.Create(outfileName) + if err != nil { + log.Fatal(err) + } + writer := csv.NewWriter(f) + writer.Write([]string{"File", "Function", "Region Number", + "Functions in File", "Regions in File", "Regions in Function", + "Times File Covered", "Percent Times File Covered", + "Times Function Covered", "Percent Times Function Covered", + "Times Region Covered", "Percent Times Region Covered"}) + + curFile := "" + for i, val := range regionCoverage { + codeRegion := BVIndexToCodeRegionMap[i] + regionsInFile := 0 + if codeRegion.FileName != curFile { + for _, v := range Structure[codeRegion.FileName] { + regionsInFile += v + } + } + + writer.Write([]string{ + codeRegion.FileName, + codeRegion.FuncName, + strconv.Itoa(i), + + strconv.Itoa(len(Structure[codeRegion.FileName])), + strconv.Itoa(regionsInFile), + strconv.Itoa(Structure[codeRegion.FileName][codeRegion.FuncName]), + + strconv.Itoa(FileCovCounts[codeRegion.FileName]), + strconv.FormatFloat(float64(FileCovCounts[codeRegion.FileName])/float64(numTrials), 'f', 4, 64), + + strconv.Itoa(FuncCovCounts[codeRegion.FuncName]), + strconv.FormatFloat(float64(FuncCovCounts[codeRegion.FuncName])/float64(numTrials), 'f', 4, 64), + + strconv.Itoa(val), + strconv.FormatFloat(float64(val)/float64(numTrials), 'f', 4, 64), + }) + + } + + writer.Flush() + f.Close() + log.Info("Finished") +} + +func worker(taskChan chan Task, resultsChan chan Result, wg *sync.WaitGroup) { + for task := range taskChan { + bv, err := pp.ReadBVFileToBV(task.Path) + if err != nil { + log.Error(err) + continue + } + + regionsCovered := 0 + + // Count number of regions covered, and ensure that any covered regions are marked as such + currentFile := "" + currentFunc := "" + markedFileCovered := true + markedFunctionCovered := true + for i, bit := range bv { + codeRegion := BVIndexToCodeRegionMap[i] + if codeRegion.FileName != currentFile { + currentFile = codeRegion.FileName + markedFileCovered = false + } + + if codeRegion.FuncName != currentFunc { + currentFunc = codeRegion.FuncName + markedFunctionCovered = false + } + + if bit { + regionsCovered++ + regionCoverageLock.Lock() + regionCoverage[i] += 1 + regionCoverageLock.Unlock() + + if !markedFileCovered { + FileCovCountLock.Lock() + if _, ok := FileCovCounts[currentFile]; !ok { + FileCovCounts[currentFile] = 0 + } + FileCovCounts[currentFile]++ + markedFileCovered = true + FileCovCountLock.Unlock() + } + + if !markedFunctionCovered { + FuncCovCountLock.Lock() + if _, ok := FuncCovCounts[currentFunc]; !ok { + FuncCovCounts[currentFunc] = 0 + } + FuncCovCounts[currentFunc]++ + markedFunctionCovered = true + FuncCovCountLock.Unlock() + } + } + } + + CompleteCounter += 1 + log.Info(CompleteCounter) + + var r Result + r.Path = task.Path + r.RegionsCovered = regionsCovered + resultsChan <- r + } + wg.Done() +} + +func writer(resultChan chan Result, wg *sync.WaitGroup, outfile string) { + + f, err := os.Create(outfile) + if err != nil { + log.Fatal(err) + } + + writer := csv.NewWriter(f) + writer.Write([]string{ + "Results Path", + "Regions RegionsCovered", + }) + + for result := range resultChan { + crawlPath := result.Path + regions := result.RegionsCovered + + writer.Write([]string{crawlPath, strconv.Itoa(regions)}) + writer.Flush() + } + wg.Done() +} diff --git a/profparse.go b/profparse.go index 5317838..4f806e6 100644 --- a/profparse.go +++ b/profparse.go @@ -658,8 +658,7 @@ func GetPathsSite(sitePath string) ([]string, error) { result := make([]string, 0) for _, sd := range subDirs { - path.Join() - result = append(result, sitePath, sd.Name()) + result = append(result, path.Join(sitePath, sd.Name())) } if len(result) == 0 { @@ -783,3 +782,14 @@ func LoadMidaResourceData(filename string) (map[string]b.DTResource, error) { return resourceData, nil } + +func CountCoveredRegions(bv []bool) (int, int) { + total := len(bv) + covered := 0 + for _, val := range bv { + if val { + covered += 1 + } + } + return covered, total +}