1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-30 16:32:50 -05:00

cups: add comprehensive CUPs setting page

- Add printers
- Delete printers
- Use polkit APIs as fallback on auth errors
- Fix ref system to conditionally subscribe to cups when wanted
This commit is contained in:
bbedward
2025-11-29 17:35:21 -05:00
parent df663aceb9
commit e6c3ae9397
31 changed files with 5993 additions and 558 deletions

View File

@@ -145,10 +145,9 @@ func TestHandleGetJobs_MissingParam(t *testing.T) {
func TestHandlePausePrinter(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().PausePrinter("printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := &Manager{
client: mockClient,
}
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
@@ -173,10 +172,9 @@ func TestHandlePausePrinter(t *testing.T) {
func TestHandleResumePrinter(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().ResumePrinter("printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := &Manager{
client: mockClient,
}
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
@@ -201,10 +199,9 @@ func TestHandleResumePrinter(t *testing.T) {
func TestHandleCancelJob(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().CancelJob(1, false).Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := &Manager{
client: mockClient,
}
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
@@ -229,10 +226,9 @@ func TestHandleCancelJob(t *testing.T) {
func TestHandlePurgeJobs(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().CancelAllJob("printer1", true).Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := &Manager{
client: mockClient,
}
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
@@ -277,3 +273,439 @@ func TestHandleRequest_UnknownMethod(t *testing.T) {
assert.Nil(t, resp.Result)
assert.NotNil(t, resp.Error)
}
func TestHandleGetDevices(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().GetDevices().Return(map[string]ipp.Attributes{
"usb://HP/LaserJet": {
"device-class": []ipp.Attribute{{Value: "direct"}},
"device-info": []ipp.Attribute{{Value: "HP LaserJet"}},
},
}, nil)
m := &Manager{client: mockClient}
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{ID: 1, Method: "cups.getDevices"}
handleGetDevices(conn, req, m)
var resp models.Response[[]Device]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.Equal(t, 1, len(*resp.Result))
}
func TestHandleGetPPDs(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().GetPPDs().Return(map[string]ipp.Attributes{
"generic.ppd": {
"ppd-make-and-model": []ipp.Attribute{{Value: "Generic"}},
},
}, nil)
m := &Manager{client: mockClient}
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{ID: 1, Method: "cups.getPPDs"}
handleGetPPDs(conn, req, m)
var resp models.Response[[]PPD]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.Equal(t, 1, len(*resp.Result))
}
func TestHandleGetClasses(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().GetClasses(mock.Anything).Return(map[string]ipp.Attributes{
"office": {
ipp.AttributePrinterName: []ipp.Attribute{{Value: "office"}},
ipp.AttributePrinterState: []ipp.Attribute{{Value: 3}},
},
}, nil)
m := &Manager{client: mockClient}
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{ID: 1, Method: "cups.getClasses"}
handleGetClasses(conn, req, m)
var resp models.Response[[]PrinterClass]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.Equal(t, 1, len(*resp.Result))
}
func TestHandleCreatePrinter(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().CreatePrinter("newprinter", "usb://HP", "generic.ppd", false, "", "", "").Return(nil)
mockClient.EXPECT().ResumePrinter("newprinter").Return(nil)
mockClient.EXPECT().AcceptJobs("newprinter").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.createPrinter",
Params: map[string]interface{}{
"name": "newprinter",
"deviceURI": "usb://HP",
"ppd": "generic.ppd",
},
}
handleCreatePrinter(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleCreatePrinter_MissingParams(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
m := &Manager{client: mockClient}
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{ID: 1, Method: "cups.createPrinter", Params: map[string]interface{}{}}
handleCreatePrinter(conn, req, m)
var resp models.Response[interface{}]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.Nil(t, resp.Result)
assert.NotNil(t, resp.Error)
}
func TestHandleDeletePrinter(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().DeletePrinter("printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.deletePrinter",
Params: map[string]interface{}{"printerName": "printer1"},
}
handleDeletePrinter(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleAcceptJobs(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().AcceptJobs("printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.acceptJobs",
Params: map[string]interface{}{"printerName": "printer1"},
}
handleAcceptJobs(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleRejectJobs(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().RejectJobs("printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.rejectJobs",
Params: map[string]interface{}{"printerName": "printer1"},
}
handleRejectJobs(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleSetPrinterShared(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().SetPrinterIsShared("printer1", true).Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.setPrinterShared",
Params: map[string]interface{}{"printerName": "printer1", "shared": true},
}
handleSetPrinterShared(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleSetPrinterLocation(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().SetPrinterLocation("printer1", "Office").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.setPrinterLocation",
Params: map[string]interface{}{"printerName": "printer1", "location": "Office"},
}
handleSetPrinterLocation(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleSetPrinterInfo(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().SetPrinterInformation("printer1", "Main Printer").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.setPrinterInfo",
Params: map[string]interface{}{"printerName": "printer1", "info": "Main Printer"},
}
handleSetPrinterInfo(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleMoveJob(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().MoveJob(1, "printer2").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.moveJob",
Params: map[string]interface{}{"jobID": float64(1), "destPrinter": "printer2"},
}
handleMoveJob(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandlePrintTestPage(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().PrintTestPage("printer1", mock.Anything, mock.Anything).Return(42, nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.printTestPage",
Params: map[string]interface{}{"printerName": "printer1"},
}
handlePrintTestPage(conn, req, m)
var resp models.Response[TestPageResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
assert.Equal(t, 42, resp.Result.JobID)
}
func TestHandleAddPrinterToClass(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().AddPrinterToClass("office", "printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.addPrinterToClass",
Params: map[string]interface{}{"className": "office", "printerName": "printer1"},
}
handleAddPrinterToClass(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleRemovePrinterFromClass(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().DeletePrinterFromClass("office", "printer1").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.removePrinterFromClass",
Params: map[string]interface{}{"className": "office", "printerName": "printer1"},
}
handleRemovePrinterFromClass(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleDeleteClass(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().DeleteClass("office").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.deleteClass",
Params: map[string]interface{}{"className": "office"},
}
handleDeleteClass(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleRestartJob(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().RestartJob(1).Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.restartJob",
Params: map[string]interface{}{"jobID": float64(1)},
}
handleRestartJob(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleHoldJob(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().HoldJobUntil(1, "indefinite").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.holdJob",
Params: map[string]interface{}{"jobID": float64(1)},
}
handleHoldJob(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}
func TestHandleHoldJob_WithHoldUntil(t *testing.T) {
mockClient := mocks_cups.NewMockCUPSClientInterface(t)
mockClient.EXPECT().HoldJobUntil(1, "no-hold").Return(nil)
mockClient.EXPECT().GetPrinters(mock.Anything).Return(map[string]ipp.Attributes{}, nil)
m := NewTestManager(mockClient, nil)
buf := &bytes.Buffer{}
conn := &mockConn{Buffer: buf}
req := Request{
ID: 1,
Method: "cups.holdJob",
Params: map[string]interface{}{"jobID": float64(1), "holdUntil": "no-hold"},
}
handleHoldJob(conn, req, m)
var resp models.Response[SuccessResult]
err := json.NewDecoder(buf).Decode(&resp)
assert.NoError(t, err)
assert.NotNil(t, resp.Result)
assert.True(t, resp.Result.Success)
}