116 lines
2.7 KiB
Go
116 lines
2.7 KiB
Go
// Mock dnf-json
|
|
//
|
|
// The purpose of this program is to return fake but expected responses to
|
|
// dnf-json depsolve and dump queries. Tests should initialise a
|
|
// dnfjson.Solver and configure it to run this program via the SetDNFJSONPath()
|
|
// method. This utility accepts queries and returns responses with the same
|
|
// structure as the dnf-json Python script.
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/osbuild/images/pkg/dnfjson"
|
|
)
|
|
|
|
func maybeFail(err error) {
|
|
if err != nil {
|
|
fail(err)
|
|
}
|
|
}
|
|
|
|
func fail(err error) {
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
func readRequest(r io.Reader) dnfjson.Request {
|
|
j := json.NewDecoder(os.Stdin)
|
|
j.DisallowUnknownFields()
|
|
|
|
var req dnfjson.Request
|
|
err := j.Decode(&req)
|
|
maybeFail(err)
|
|
return req
|
|
}
|
|
|
|
func readTestCase() string {
|
|
if len(os.Args) < 2 {
|
|
fail(errors.New("no test case specified"))
|
|
}
|
|
if len(os.Args) > 2 {
|
|
fail(errors.New("invalid number of arguments: you must specify a test case"))
|
|
}
|
|
return os.Args[1]
|
|
}
|
|
|
|
func parseResponse(resp []byte, req dnfjson.Request) json.RawMessage {
|
|
parsedResponse := make(map[string]json.RawMessage)
|
|
err := json.Unmarshal(resp, &parsedResponse)
|
|
maybeFail(err)
|
|
|
|
if req.Command == "search" {
|
|
// Search requests need to return results based on the search
|
|
// The key to the search is a comma-separated list of the requested packages
|
|
key := strings.Join(req.Arguments.Search.Packages, ",")
|
|
|
|
// Extract the possible response map
|
|
var searches map[string]json.RawMessage
|
|
err = json.Unmarshal(parsedResponse["search"], &searches)
|
|
maybeFail(err)
|
|
|
|
if _, ok := searches[key]; !ok {
|
|
fail(fmt.Errorf("search response map is missing key = %s", key))
|
|
}
|
|
return searches[key]
|
|
} else {
|
|
return parsedResponse[req.Command]
|
|
}
|
|
}
|
|
|
|
func checkForError(msg json.RawMessage) bool {
|
|
j := json.NewDecoder(bytes.NewReader(msg))
|
|
j.DisallowUnknownFields()
|
|
dnferror := new(dnfjson.Error)
|
|
err := j.Decode(dnferror)
|
|
return err == nil
|
|
}
|
|
|
|
func main() {
|
|
testFilePath := readTestCase()
|
|
|
|
req := readRequest(os.Stdin)
|
|
|
|
testFile, err := os.Open(testFilePath)
|
|
if err != nil {
|
|
fail(fmt.Errorf("failed to open test file %q\n", testFilePath))
|
|
}
|
|
defer testFile.Close()
|
|
response, err := io.ReadAll(testFile)
|
|
if err != nil {
|
|
fail(fmt.Errorf("failed to read test file %q\n", testFilePath))
|
|
}
|
|
|
|
res := parseResponse(response, req)
|
|
|
|
if req.Command == "depsolve" {
|
|
// add repo ID to packages
|
|
// just use the first
|
|
for _, repo := range req.Arguments.Repos {
|
|
res = bytes.ReplaceAll(res, []byte("REPOID"), []byte(repo.ID))
|
|
break
|
|
}
|
|
}
|
|
fmt.Print(string(res))
|
|
|
|
// check if we should return with error
|
|
if checkForError(res) {
|
|
os.Exit(1)
|
|
}
|
|
}
|