librclone: add tests for build and execute them in the actions #4891

This commit is contained in:
Nick Craig-Wood 2021-03-30 11:37:59 +01:00
parent f38c262471
commit 62bf63d36f
4 changed files with 74 additions and 8 deletions

View File

@ -36,6 +36,7 @@ jobs:
check: true check: true
quicktest: true quicktest: true
racequicktest: true racequicktest: true
librclonetest: true
deploy: true deploy: true
- job_name: mac_amd64 - job_name: mac_amd64
@ -193,6 +194,13 @@ jobs:
make racequicktest make racequicktest
if: matrix.racequicktest if: matrix.racequicktest
- name: Run librclone tests
shell: bash
run: |
make -C librclone/ctest test
make -C librclone/ctest clean
if: matrix.librclonetest
- name: Code quality test - name: Code quality test
shell: bash shell: bash
run: | run: |

View File

@ -10,5 +10,8 @@ ctest.o: ctest.c librclone.h
librclone.a librclone.h: librclone.a librclone.h:
go build --buildmode=c-archive -o librclone.a github.com/rclone/rclone/librclone go build --buildmode=c-archive -o librclone.a github.com/rclone/rclone/librclone
test: ctest
./ctest
clean: clean:
rm -f tmp ctest *.o *.a *.h *.gch rm -f tmp ctest *.o *.a *.h *.gch

View File

@ -1,3 +1,6 @@
/*
This is a very simple test/demo program for librclone's C interface
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -14,21 +17,73 @@ void testRPC(char *method, char *in) {
// noop command // noop command
void testNoOp() { void testNoOp() {
printf("test rc/noop\n"); printf("test rc/noop\n");
testRPC("rc/noop", struct RcloneRPCResult out = RcloneRPC("rc/noop", "{"
"{"
" \"p1\": [1,\"2\",null,4]," " \"p1\": [1,\"2\",null,4],"
" \"p2\": { \"a\":1, \"b\":2 } " " \"p2\": { \"a\":1, \"b\":2 } "
"}"); "}");
printf("status: %d\n", out.Status);
printf("output: %s\n", out.Output);
const char *expected =
"{\n"
"\t\"p1\": [\n"
"\t\t1,\n"
"\t\t\"2\",\n"
"\t\tnull,\n"
"\t\t4\n"
"\t],\n"
"\t\"p2\": {\n"
"\t\t\"a\": 1,\n"
"\t\t\"b\": 2\n"
"\t}\n"
"}\n";
if (strcmp(expected, out.Output) != 0) {
fprintf(stderr, "Wrong output.\nWant:\n%s\nGot:\n%s\n", expected, out.Output);
exit(EXIT_FAILURE);
}
if (out.Status != 200) {
fprintf(stderr, "Wrong status: want: %d: got: %d\n", 200, out.Status);
exit(EXIT_FAILURE);
}
free(out.Output);
} }
// error command // error command
void testError() { void testError() {
printf("test rc/error\n"); printf("test rc/error\n");
testRPC("rc/error", struct RcloneRPCResult out = RcloneRPC("rc/error",
"{" "{"
" \"p1\": [1,\"2\",null,4]," " \"p1\": [1,\"2\",null,4],"
" \"p2\": { \"a\":1, \"b\":2 } " " \"p2\": { \"a\":1, \"b\":2 } "
"}"); "}");
printf("status: %d\n", out.Status);
printf("output: %s\n", out.Output);
const char *expected =
"{\n"
"\t\"error\": \"arbitrary error on input map[p1:[1 2 \\u003cnil\\u003e 4] p2:map[a:1 b:2]]\",\n"
"\t\"input\": {\n"
"\t\t\"p1\": [\n"
"\t\t\t1,\n"
"\t\t\t\"2\",\n"
"\t\t\tnull,\n"
"\t\t\t4\n"
"\t\t],\n"
"\t\t\"p2\": {\n"
"\t\t\t\"a\": 1,\n"
"\t\t\t\"b\": 2\n"
"\t\t}\n"
"\t},\n"
"\t\"path\": \"rc/error\",\n"
"\t\"status\": 500\n"
"}\n";
if (strcmp(expected, out.Output) != 0) {
fprintf(stderr, "Wrong output.\nWant:\n%s\nGot:\n%s\n", expected, out.Output);
exit(EXIT_FAILURE);
}
if (out.Status != 500) {
fprintf(stderr, "Wrong status: want: %d: got: %d\n", 500, out.Status);
exit(EXIT_FAILURE);
}
free(out.Output);
} }
// copy file using "operations/copyfile" command // copy file using "operations/copyfile" command
@ -55,8 +110,8 @@ int main(int argc, char** argv) {
testNoOp(); testNoOp();
testError(); testError();
testCopyFile(); /* testCopyFile(); */
testListRemotes(); /* testListRemotes(); */
RcloneFinalize(); RcloneFinalize();
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -79,7 +79,7 @@ func RcloneFinalize() {
// //
// Output will be returned as a serialized JSON object // Output will be returned as a serialized JSON object
// Status is a HTTP status return (200=OK anything else fail) // Status is a HTTP status return (200=OK anything else fail)
type RcloneRPCResult struct { type RcloneRPCResult struct { //nolint:deadcode
Output *C.char Output *C.char
Status C.int Status C.int
} }
@ -113,12 +113,12 @@ type RcloneMobileRPCResult struct {
Status int Status int
} }
// RcloneMobileRPCRPC this works the same as RcloneRPC but has an interface // RcloneMobileRPC works the same as RcloneRPC but has an interface
// optimised for gomobile, in particular the function signature is // optimised for gomobile, in particular the function signature is
// valid under gobind rules. // valid under gobind rules.
// //
// https://pkg.go.dev/golang.org/x/mobile/cmd/gobind#hdr-Type_restrictions // https://pkg.go.dev/golang.org/x/mobile/cmd/gobind#hdr-Type_restrictions
func RcloneMobileRPCRPC(method string, input string) (result RcloneMobileRPCResult) { func RcloneMobileRPC(method string, input string) (result RcloneMobileRPCResult) { //nolint:deadcode
output, status := callFunctionJSON(method, input) output, status := callFunctionJSON(method, input)
result.Output = output result.Output = output
result.Status = status result.Status = status