mirror of
https://gitlab.com/TECHNOFAB/nixtest.git
synced 2025-12-12 02:00:18 +01:00
chore: initial prototype
This commit is contained in:
commit
c1c19c324d
16 changed files with 1099 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake . --impure --accept-flake-config
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
.direnv/
|
||||||
|
.devenv/
|
||||||
|
result
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
*.xml
|
||||||
78
cmd/nixtest/display.go
Normal file
78
cmd/nixtest/display.go
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
|
"github.com/jedib0t/go-pretty/v6/text"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printErrors(results Results) {
|
||||||
|
for _, suiteResults := range results {
|
||||||
|
for _, result := range suiteResults {
|
||||||
|
if result.Success {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Println(text.FgRed.Sprintf("⚠ Test \"%s\" failed:", result.Name))
|
||||||
|
for line := range strings.Lines(result.Error) {
|
||||||
|
fmt.Printf("%s %s", text.FgRed.Sprint("|"), line)
|
||||||
|
}
|
||||||
|
if result.Error == "" {
|
||||||
|
fmt.Printf("- no output -")
|
||||||
|
}
|
||||||
|
fmt.Printf("\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSummary(results Results, successCount int, totalCount int) {
|
||||||
|
t := table.NewWriter()
|
||||||
|
t.SetStyle(table.StyleLight)
|
||||||
|
t.SetOutputMirror(os.Stdout)
|
||||||
|
t.AppendHeader(table.Row{"Test", "Duration", "Pass", "File"})
|
||||||
|
|
||||||
|
log.Info().Msg("Summary:")
|
||||||
|
|
||||||
|
for suite, suiteResults := range results {
|
||||||
|
suiteTotal := len(suiteResults)
|
||||||
|
suiteSuccess := 0
|
||||||
|
|
||||||
|
for _, res := range suiteResults {
|
||||||
|
if res.Success {
|
||||||
|
suiteSuccess++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.AppendRow(table.Row{
|
||||||
|
text.Bold.Sprint(suite),
|
||||||
|
"",
|
||||||
|
fmt.Sprintf("%d/%d", suiteSuccess, suiteTotal),
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
for _, res := range suiteResults {
|
||||||
|
symbol := "❌"
|
||||||
|
if res.Success {
|
||||||
|
symbol = "✅"
|
||||||
|
}
|
||||||
|
|
||||||
|
t.AppendRow([]any{
|
||||||
|
res.Name,
|
||||||
|
fmt.Sprintf("%s", res.Duration),
|
||||||
|
symbol,
|
||||||
|
res.Pos,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
t.AppendSeparator()
|
||||||
|
}
|
||||||
|
|
||||||
|
t.AppendFooter(table.Row{
|
||||||
|
text.Bold.Sprint("TOTAL"),
|
||||||
|
"",
|
||||||
|
fmt.Sprintf("%d/%d", successCount, totalCount),
|
||||||
|
"",
|
||||||
|
})
|
||||||
|
t.Render()
|
||||||
|
}
|
||||||
115
cmd/nixtest/junit.go
Normal file
115
cmd/nixtest/junit.go
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JUnitReport struct {
|
||||||
|
XMLName xml.Name `xml:"testsuite"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Tests int `xml:"tests,attr"`
|
||||||
|
Failures int `xml:"failures,attr"`
|
||||||
|
Time string `xml:"time,attr"` // in seconds
|
||||||
|
Suites []JUnitTestSuite `xml:"testsuite"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JUnitTestSuite struct {
|
||||||
|
XMLName xml.Name `xml:"testsuite"`
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Tests int `xml:"tests,attr"`
|
||||||
|
Failures int `xml:"failures,attr"`
|
||||||
|
Time string `xml:"time,attr"` // in seconds
|
||||||
|
TestCases []JUnitCase `xml:"testcase"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JUnitCase struct {
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Classname string `xml:"classname,attr"`
|
||||||
|
Time string `xml:"time,attr"` // in seconds
|
||||||
|
File string `xml:"file,attr,omitempty"`
|
||||||
|
Line string `xml:"line,attr,omitempty"`
|
||||||
|
Failure *string `xml:"failure,omitempty"`
|
||||||
|
Error *string `xml:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateJUnitReport(name string, results Results) (string, error) {
|
||||||
|
report := JUnitReport{
|
||||||
|
Name: name,
|
||||||
|
Tests: 0,
|
||||||
|
Failures: 0,
|
||||||
|
Suites: []JUnitTestSuite{},
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDuration := time.Duration(0)
|
||||||
|
|
||||||
|
for suiteName, suiteResults := range results {
|
||||||
|
suite := JUnitTestSuite{
|
||||||
|
Name: suiteName,
|
||||||
|
Tests: len(suiteResults),
|
||||||
|
Failures: 0,
|
||||||
|
TestCases: []JUnitCase{},
|
||||||
|
}
|
||||||
|
|
||||||
|
suiteDuration := time.Duration(0)
|
||||||
|
|
||||||
|
for _, result := range suiteResults {
|
||||||
|
durationSeconds := fmt.Sprintf("%.3f", result.Duration.Seconds())
|
||||||
|
totalDuration += result.Duration
|
||||||
|
suiteDuration += result.Duration
|
||||||
|
|
||||||
|
testCase := JUnitCase{
|
||||||
|
Name: result.Name,
|
||||||
|
Classname: suiteName, // Use suite name as classname
|
||||||
|
Time: durationSeconds,
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.Pos != "" {
|
||||||
|
pos := strings.Split(result.Pos, ":")
|
||||||
|
testCase.File = pos[0]
|
||||||
|
testCase.Line = pos[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.Success {
|
||||||
|
suite.Failures++
|
||||||
|
report.Failures++
|
||||||
|
testCase.Failure = &result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.TestCases = append(suite.TestCases, testCase)
|
||||||
|
}
|
||||||
|
suite.Time = fmt.Sprintf("%.3f", suiteDuration.Seconds())
|
||||||
|
report.Suites = append(report.Suites, suite)
|
||||||
|
report.Tests += len(suiteResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
report.Time = fmt.Sprintf("%.3f", totalDuration.Seconds())
|
||||||
|
|
||||||
|
output, err := xml.MarshalIndent(report, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to marshal XML: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return xml.Header + string(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateJunitFile(path string, results Results) error {
|
||||||
|
res, err := GenerateJUnitReport("nixtest", results)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate junit report: %w", err)
|
||||||
|
}
|
||||||
|
file, err := os.Create(*junitPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create file: %w", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
_, err = file.WriteString(res)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to write to file: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
270
cmd/nixtest/main.go
Normal file
270
cmd/nixtest/main.go
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/sergi/go-diff/diffmatchpatch"
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SuiteSpec struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Tests []TestSpec `json:"tests"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestSpec struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Expected any `json:"expected,omitempty"`
|
||||||
|
Actual any `json:"actual,omitempty"`
|
||||||
|
ActualDrv string `json:"actualDrv,omitempty"`
|
||||||
|
Pos string `json:"pos,omitempty"`
|
||||||
|
|
||||||
|
Suite string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestResult struct {
|
||||||
|
Name string
|
||||||
|
Success bool
|
||||||
|
Error string
|
||||||
|
Duration time.Duration
|
||||||
|
Pos string
|
||||||
|
Suite string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Results map[string][]TestResult
|
||||||
|
|
||||||
|
func buildAndParse(variable string) (any, error) {
|
||||||
|
cmd := exec.Command(
|
||||||
|
"nix",
|
||||||
|
"build",
|
||||||
|
variable+"^*",
|
||||||
|
"--print-out-paths",
|
||||||
|
"--no-link",
|
||||||
|
)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := strings.TrimSpace(string(output))
|
||||||
|
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result any
|
||||||
|
err = json.Unmarshal(data, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTest(spec TestSpec) TestResult {
|
||||||
|
startTime := time.Now()
|
||||||
|
result := TestResult{
|
||||||
|
Name: spec.Name,
|
||||||
|
Pos: spec.Pos,
|
||||||
|
Suite: spec.Suite,
|
||||||
|
Success: false,
|
||||||
|
Error: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual any
|
||||||
|
var expected any
|
||||||
|
|
||||||
|
if spec.Type == "snapshot" {
|
||||||
|
actual = spec.Actual
|
||||||
|
filePath := path.Join(
|
||||||
|
*snapshotDir,
|
||||||
|
fmt.Sprintf("%s.snap.json", strings.ToLower(spec.Name)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if *updateSnapshots {
|
||||||
|
createSnapshot(filePath, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) {
|
||||||
|
result.Error = "No Snapshot exists yet"
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
expected, err = ParseFile[any](filePath)
|
||||||
|
if err != nil {
|
||||||
|
result.Error = fmt.Sprintf("[system] failed to parse snapshot: %v", err.Error())
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
} else if spec.Type == "unit" {
|
||||||
|
if spec.ActualDrv != "" {
|
||||||
|
var err error
|
||||||
|
actual, err = buildAndParse(spec.ActualDrv)
|
||||||
|
if err != nil {
|
||||||
|
result.Error = fmt.Sprintf("[system] failed to parse drv output: %v", err.Error())
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actual = spec.Actual
|
||||||
|
}
|
||||||
|
expected = spec.Expected
|
||||||
|
} else {
|
||||||
|
log.Panic().Str("type", spec.Type).Msg("Invalid test type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if reflect.DeepEqual(actual, expected) {
|
||||||
|
result.Success = true
|
||||||
|
} else {
|
||||||
|
dmp := diffmatchpatch.New()
|
||||||
|
text1, err := json.MarshalIndent(actual, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
result.Error = fmt.Sprintf("[system] failed to json marshal 'actual': %v", err.Error())
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
text2, err := json.MarshalIndent(expected, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
result.Error = fmt.Sprintf("[system] failed to json marshal 'expected': %v", err.Error())
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
diffs := dmp.DiffMain(string(text1), string(text2), false)
|
||||||
|
result.Error = fmt.Sprintf("Mismatch:\n%s", dmp.DiffPrettyText(diffs))
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
result.Duration = time.Since(startTime)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSnapshot(filePath string, actual any) error {
|
||||||
|
jsonData, err := json.Marshal(actual)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(path.Dir(filePath), 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(filePath, jsonData, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// worker to process TestSpec items
|
||||||
|
func worker(jobs <-chan TestSpec, results chan<- TestResult, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
for spec := range jobs {
|
||||||
|
results <- runTest(spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
numWorkers *int = flag.Int("workers", 4, "Amount of tests to run in parallel")
|
||||||
|
testsFile *string = flag.String("tests", "", "Path to JSON file containing tests")
|
||||||
|
snapshotDir *string = flag.String(
|
||||||
|
"snapshot-dir", "./snapshots", "Directory where snapshots are stored",
|
||||||
|
)
|
||||||
|
junitPath *string = flag.String(
|
||||||
|
"junit", "", "Path to generate JUNIT report to, leave empty to disable",
|
||||||
|
)
|
||||||
|
updateSnapshots *bool = flag.Bool("update-snapshots", false, "Update all snapshots")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
|
|
||||||
|
log.Info().
|
||||||
|
Int("workers", *numWorkers).
|
||||||
|
Msg("Starting nixtest")
|
||||||
|
|
||||||
|
if _, err := os.Stat(*testsFile); errors.Is(err, os.ErrNotExist) {
|
||||||
|
log.Error().Str("file", *testsFile).Msg("Tests file does not exist")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedSpecs, err := ParseFile[[]SuiteSpec](*testsFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to load tests from file")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalTests := 0
|
||||||
|
for _, suite := range parsedSpecs {
|
||||||
|
totalTests += len(suite.Tests)
|
||||||
|
}
|
||||||
|
log.Info().
|
||||||
|
Int("suites", len(parsedSpecs)).
|
||||||
|
Int("tests", totalTests).
|
||||||
|
Msg("Discovered suites")
|
||||||
|
|
||||||
|
jobsChan := make(chan TestSpec, totalTests)
|
||||||
|
resultsChan := make(chan TestResult, totalTests)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for i := 1; i <= *numWorkers; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go worker(jobsChan, resultsChan, &wg)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, suite := range parsedSpecs {
|
||||||
|
for _, test := range suite.Tests {
|
||||||
|
test.Suite = suite.Name
|
||||||
|
jobsChan <- test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(jobsChan)
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(resultsChan)
|
||||||
|
|
||||||
|
results := map[string][]TestResult{}
|
||||||
|
|
||||||
|
successCount := 0
|
||||||
|
|
||||||
|
for r := range resultsChan {
|
||||||
|
results[r.Suite] = append(results[r.Suite], r)
|
||||||
|
if r.Success {
|
||||||
|
successCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *junitPath != "" {
|
||||||
|
err = GenerateJunitFile(*junitPath, results)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to generate junit file")
|
||||||
|
} else {
|
||||||
|
log.Info().Str("path", *junitPath).Msg("Generated Junit report")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print errors/logs of failed tests
|
||||||
|
printErrors(results)
|
||||||
|
|
||||||
|
// show table summary
|
||||||
|
printSummary(results, successCount, totalTests)
|
||||||
|
|
||||||
|
if successCount != totalTests {
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
24
cmd/nixtest/utils.go
Normal file
24
cmd/nixtest/utils.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseFile[T any](filePath string) (result T, err error) {
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("failed to open file %s: %w", filePath, err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(file)
|
||||||
|
|
||||||
|
err = decoder.Decode(&result)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("failed to decode JSON from file %s: %w", filePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
345
flake.lock
generated
Normal file
345
flake.lock
generated
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"cachix": {
|
||||||
|
"inputs": {
|
||||||
|
"devenv": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"git-hooks": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1742042642,
|
||||||
|
"narHash": "sha256-D0gP8srrX0qj+wNYNPdtVJsQuFzIng3q43thnHXQ/es=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "cachix",
|
||||||
|
"rev": "a624d3eaf4b1d225f918de8543ed739f2f574203",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "latest",
|
||||||
|
"repo": "cachix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devenv": {
|
||||||
|
"inputs": {
|
||||||
|
"cachix": "cachix",
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"git-hooks": "git-hooks",
|
||||||
|
"nix": "nix",
|
||||||
|
"nixpkgs": "nixpkgs_3"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1746189866,
|
||||||
|
"narHash": "sha256-3sTvuSVBFcXbqg26Qcw/ENJ1s36jtzEcZ0mHqLqvWRA=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"rev": "5fc592d45dd056035e0fd5000893a21609c35526",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733328505,
|
||||||
|
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"devenv",
|
||||||
|
"nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1712014858,
|
||||||
|
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1743550720,
|
||||||
|
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"git-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1742649964,
|
||||||
|
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"devenv",
|
||||||
|
"git-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libgit2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1697646580,
|
||||||
|
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
|
||||||
|
"owner": "libgit2",
|
||||||
|
"repo": "libgit2",
|
||||||
|
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "libgit2",
|
||||||
|
"repo": "libgit2",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"libgit2": "libgit2",
|
||||||
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixpkgs-23-11": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"nixpkgs-regression": [
|
||||||
|
"devenv"
|
||||||
|
],
|
||||||
|
"pre-commit-hooks": [
|
||||||
|
"devenv"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1745930071,
|
||||||
|
"narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=",
|
||||||
|
"owner": "domenkozar",
|
||||||
|
"repo": "nix",
|
||||||
|
"rev": "b455edf3505f1bf0172b39a735caef94687d0d9c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "domenkozar",
|
||||||
|
"ref": "devenv-2.24",
|
||||||
|
"repo": "nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733212471,
|
||||||
|
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1743296961,
|
||||||
|
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1717432640,
|
||||||
|
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "release-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_3": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733477122,
|
||||||
|
"narHash": "sha256-qamMCz5mNpQmgBwc8SB5tVMlD5sbwVIToVZtSxMph9s=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"rev": "7bd9e84d0452f6d2e63b6e6da29fe73fac951857",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "rolling",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_4": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1746152631,
|
||||||
|
"narHash": "sha256-zBuvmL6+CUsk2J8GINpyy8Hs1Zp4PP6iBWSmZ4SCQ/s=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "032bc6539bd5f14e9d0c51bd79cfe9a055b094c3",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_5": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1745377448,
|
||||||
|
"narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"devenv": "devenv",
|
||||||
|
"flake-parts": "flake-parts_2",
|
||||||
|
"nixpkgs": "nixpkgs_4",
|
||||||
|
"systems": "systems",
|
||||||
|
"treefmt-nix": "treefmt-nix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689347949,
|
||||||
|
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-linux",
|
||||||
|
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-linux",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"treefmt-nix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs_5"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1746216483,
|
||||||
|
"narHash": "sha256-4h3s1L/kKqt3gMDcVfN8/4v2jqHrgLIe4qok4ApH5x4=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "29ec5026372e0dec56f890e50dbe4f45930320fd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
100
flake.nix
Normal file
100
flake.nix
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
{
|
||||||
|
outputs = {
|
||||||
|
flake-parts,
|
||||||
|
systems,
|
||||||
|
...
|
||||||
|
} @ inputs:
|
||||||
|
flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
|
imports = [
|
||||||
|
inputs.devenv.flakeModule
|
||||||
|
inputs.treefmt-nix.flakeModule
|
||||||
|
./lib/flakeModule.nix
|
||||||
|
];
|
||||||
|
systems = import systems;
|
||||||
|
flake = {};
|
||||||
|
perSystem = {
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
treefmt = {
|
||||||
|
projectRootFile = "flake.nix";
|
||||||
|
programs = {
|
||||||
|
alejandra.enable = true;
|
||||||
|
mdformat.enable = true;
|
||||||
|
gofmt.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
devenv.shells.default = {
|
||||||
|
containers = pkgs.lib.mkForce {};
|
||||||
|
packages = [pkgs.gopls pkgs.gore];
|
||||||
|
|
||||||
|
languages.go.enable = true;
|
||||||
|
|
||||||
|
pre-commit.hooks = {
|
||||||
|
treefmt = {
|
||||||
|
enable = true;
|
||||||
|
packageOverrides.treefmt = config.treefmt.build.wrapper;
|
||||||
|
};
|
||||||
|
convco.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testSuites = {
|
||||||
|
"suite-one" = [
|
||||||
|
{
|
||||||
|
name = "test-one";
|
||||||
|
# required to figure out file and line, but optional
|
||||||
|
pos = __curPos;
|
||||||
|
expected = 1;
|
||||||
|
actual = 1;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "fail";
|
||||||
|
expected = 0;
|
||||||
|
actual = "meow";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "snapshot-test";
|
||||||
|
type = "snapshot";
|
||||||
|
pos = __curPos;
|
||||||
|
actual = "test";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
"other-suite" = [
|
||||||
|
{
|
||||||
|
name = "obj-snapshot";
|
||||||
|
type = "snapshot";
|
||||||
|
actual = {hello = "world";};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
packages.default = pkgs.callPackage ./package.nix {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
|
||||||
|
# flake & devenv related
|
||||||
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
|
systems.url = "github:nix-systems/default-linux";
|
||||||
|
devenv.url = "github:cachix/devenv";
|
||||||
|
treefmt-nix.url = "github:numtide/treefmt-nix";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixConfig = {
|
||||||
|
extra-substituters = [
|
||||||
|
"https://cache.nixos.org/"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
"https://devenv.cachix.org"
|
||||||
|
];
|
||||||
|
|
||||||
|
extra-trusted-public-keys = [
|
||||||
|
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
22
go.mod
Normal file
22
go.mod
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
module gitlab.com/technofab/testnix
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/rs/zerolog v1.34.0
|
||||||
|
github.com/spf13/pflag v1.0.6
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
golang.org/x/text v0.22.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.6.7
|
||||||
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/sergi/go-diff v1.3.1
|
||||||
|
golang.org/x/sys v0.32.0 // indirect
|
||||||
|
)
|
||||||
43
go.sum
Normal file
43
go.sum
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo=
|
||||||
|
github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
|
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||||
|
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||||
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
|
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||||
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||||
|
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
31
lib/default.nix
Normal file
31
lib/default.nix
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{pkgs, ...}: {
|
||||||
|
mkTest = {
|
||||||
|
type ? "unit",
|
||||||
|
name,
|
||||||
|
description ? "",
|
||||||
|
expected ? null,
|
||||||
|
actual ? null,
|
||||||
|
actualDrv ? null,
|
||||||
|
pos ? null,
|
||||||
|
}: {
|
||||||
|
inherit type name description expected actual;
|
||||||
|
actualDrv = actualDrv.drvPath or "";
|
||||||
|
pos =
|
||||||
|
if pos == null
|
||||||
|
then ""
|
||||||
|
else "${pos.file}:${toString pos.line}:${toString pos.column}";
|
||||||
|
};
|
||||||
|
mkSuite = name: tests: {
|
||||||
|
inherit name tests;
|
||||||
|
};
|
||||||
|
exportSuites = suites: let
|
||||||
|
suitesList =
|
||||||
|
if builtins.isList suites
|
||||||
|
then suites
|
||||||
|
else [suites];
|
||||||
|
testsMapped = builtins.toJSON suitesList;
|
||||||
|
in
|
||||||
|
pkgs.runCommand "tests.json" {} ''
|
||||||
|
echo '${testsMapped}' > $out
|
||||||
|
'';
|
||||||
|
}
|
||||||
6
lib/flake.nix
Normal file
6
lib/flake.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
outputs = inputs: {
|
||||||
|
lib = import ./.;
|
||||||
|
flakeModule = import ./flakeModule.nix;
|
||||||
|
};
|
||||||
|
}
|
||||||
41
lib/flakeModule.nix
Normal file
41
lib/flakeModule.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
flake-parts-lib,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
in {
|
||||||
|
options.perSystem = flake-parts-lib.mkPerSystemOption (
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
nixtests-lib = import ./. {inherit pkgs;};
|
||||||
|
in {
|
||||||
|
options.testSuites = mkOption {
|
||||||
|
type = types.attrsOf (types.listOf types.attrs);
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.legacyPackages = rec {
|
||||||
|
"nixtests" = let
|
||||||
|
suites = map (suiteName: let
|
||||||
|
tests = builtins.getAttr suiteName config.testSuites;
|
||||||
|
in
|
||||||
|
nixtests-lib.mkSuite
|
||||||
|
suiteName
|
||||||
|
(map (test: nixtests-lib.mkTest test) tests))
|
||||||
|
(builtins.attrNames config.testSuites);
|
||||||
|
in
|
||||||
|
nixtests-lib.exportSuites suites;
|
||||||
|
"nixtests:run" = let
|
||||||
|
program = pkgs.callPackage ./../package.nix {};
|
||||||
|
in
|
||||||
|
pkgs.writeShellScriptBin "nixtests:run" ''
|
||||||
|
${program}/bin/nixtest --tests=${nixtests} "$@"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
16
package.nix
Normal file
16
package.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{buildGoModule, ...}:
|
||||||
|
buildGoModule {
|
||||||
|
name = "nixtest";
|
||||||
|
src =
|
||||||
|
# filter everything except for cmd/ and go.mod, go.sum
|
||||||
|
builtins.filterSource (
|
||||||
|
path: type:
|
||||||
|
builtins.match ".*(/cmd/?.*|/go\.(mod|sum))$"
|
||||||
|
path
|
||||||
|
!= null
|
||||||
|
)
|
||||||
|
./.;
|
||||||
|
subPackages = ["cmd/nixtest"];
|
||||||
|
vendorHash = "sha256-H0KiuTqY2cxsUvqoxWAHKHjdfsBHjYkqxdYgTY0ftes=";
|
||||||
|
meta.mainProgram = "nixtest";
|
||||||
|
}
|
||||||
1
snapshots/obj-snapshot.snap.json
Normal file
1
snapshots/obj-snapshot.snap.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"bye":"world"}
|
||||||
1
snapshots/snapshot-test.snap.json
Normal file
1
snapshots/snapshot-test.snap.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"test"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue