Skip to content

Commit

Permalink
Add option to split files by line count
Browse files Browse the repository at this point in the history
  • Loading branch information
leonid-shevtsov committed Feb 7, 2017
1 parent 7ff9693 commit 5a22ffe
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 12 deletions.
44 changes: 44 additions & 0 deletions line_count.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"bytes"
"io"
"os"
)

func estimateFileTimesByLineCount(currentFileSet map[string]bool, fileTimes map[string]float64) {
for fileName := range currentFileSet {
file, err := os.Open(fileName)
if err != nil {
printMsg("failed to count lines in file %s: %v\n", file, err)
continue
}
defer file.Close()
lineCount, err := lineCounter(file)
if err != nil {
printMsg("failed to count lines in file %s: %v\n", file, err)
continue
}
fileTimes[fileName] = float64(lineCount)
}
}

// Credit to http://stackoverflow.com/a/24563853/6678
func lineCounter(r io.Reader) (int, error) {
buf := make([]byte, 32*1024)
count := 0
lineSep := []byte{'\n'}

for {
c, err := r.Read(buf)
count += bytes.Count(buf[:c], lineSep)

switch {
case err == io.EOF:
return count, nil

case err != nil:
return count, err
}
}
}
31 changes: 19 additions & 12 deletions split_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

var useCircleCI bool
var useJUnitXML bool
var useLineCount bool
var junitXMLPath string
var testFilePattern = ""
var circleCIProjectPrefix = ""
Expand Down Expand Up @@ -56,7 +57,9 @@ func addNewFiles(fileTimes map[string]float64, currentFileSet map[string]bool) {
if _, isSet := fileTimes[file]; isSet {
continue
}
printMsg("missing file time for %s\n", file)
if useCircleCI || useJUnitXML {
printMsg("missing file time for %s\n", file)
}
fileTimes[file] = averageFileTime
}
}
Expand Down Expand Up @@ -94,12 +97,14 @@ func parseFlags() {
flag.IntVar(&splitTotal, "split-total", -1, "Total number of containers (or set CIRCLE_NODE_TOTAL)")

flag.StringVar(&circleCIAPIKey, "circleci-key", "", "CircleCI API key (or set CIRCLECI_API_KEY environment variable) - required to use CircleCI")
flag.StringVar(&circleCIProjectPrefix, "circleci-project", "", "CircleCI project name (e.g. github/leonid-shevtsov/circleci-test-balancer) - required to use CircleCI")
flag.StringVar(&circleCIProjectPrefix, "circleci-project", "", "CircleCI project name (e.g. github/leonid-shevtsov/split_tests) - required to use CircleCI")
flag.StringVar(&circleCIBranchName, "circleci-branch", "", "Current branch for CircleCI (or set CIRCLE_BRANCH) - required to use CircleCI")

flag.BoolVar(&useJUnitXML, "junit", false, "Use a JUnit XML report for test times")
flag.StringVar(&junitXMLPath, "junit-path", "", "Path to a JUnit XML report (leave empty to read from stdin)")

flag.BoolVar(&useLineCount, "line-count", false, "Use line count to estimate test times")

var showHelp bool
flag.BoolVar(&showHelp, "help", false, "Show this help text")

Expand All @@ -126,7 +131,6 @@ func parseFlags() {
}

useCircleCI = circleCIAPIKey != ""
showHelp = showHelp || !useCircleCI && !useJUnitXML

if showHelp {
printMsg("Splits test files into containers of even duration\n\n")
Expand All @@ -144,25 +148,28 @@ func parseFlags() {
func main() {
parseFlags()

fileTimes := make(map[string]float64)
if useJUnitXML {
getFileTimesFromJUnitXML(fileTimes)
} else if useCircleCI {
getFileTimesFromCircleCI(fileTimes)
}

currentFiles, _ := zglob.Glob(testFilePattern)
currentFileSet := make(map[string]bool)

for _, file := range currentFiles {
currentFileSet[file] = true
}

fileTimes := make(map[string]float64)
if useLineCount {
estimateFileTimesByLineCount(currentFileSet, fileTimes)
} else if useJUnitXML {
getFileTimesFromJUnitXML(fileTimes)
} else if useCircleCI {
getFileTimesFromCircleCI(fileTimes)
}

removeDeletedFiles(fileTimes, currentFileSet)
addNewFiles(fileTimes, currentFileSet)

buckets, bucketTimes := splitFiles(fileTimes, splitTotal)
printMsg("expected test time: %0.1fs\n", bucketTimes[splitIndex])
if useCircleCI || useJUnitXML {
printMsg("expected test time: %0.1fs\n", bucketTimes[splitIndex])
}

fmt.Println(strings.Join(buckets[splitIndex], " "))
}

0 comments on commit 5a22ffe

Please sign in to comment.