jellyfin-smart-playlist/Tests/Tests.cs

272 lines
12 KiB
C#

using Lisp_Boolean = Jellyfin.Plugin.SmartPlaylist.Lisp.Boolean;
using Lisp_Object = Jellyfin.Plugin.SmartPlaylist.Lisp.Object;
using Lisp_Integer = Jellyfin.Plugin.SmartPlaylist.Lisp.Integer;
using Jellyfin.Plugin.SmartPlaylist.Lisp;
using Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler;
namespace Tests
{
public class O {
int _i;
bool _b;
public O(int i, bool b) {
_i = i;
_b = b;
}
public int i { get => _i; }
public bool b { get => _b; }
public int I() {
return _i;
}
public string G<E>() {
return typeof(E).FullName;
}
}
public class Test {
[Fact]
public static void TestTokenizer() {
StringTokenStream sts = StringTokenStream.generate("(\"some literal string\" def ghj +100 -+300 1 >= ++ !=)");
Assert.Equal("(", sts.Get().value);
Assert.Equal("\"", sts.Get().value);
Assert.Equal("some", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("literal", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("string", sts.Get().value);
Assert.Equal("\"", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("def", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("ghj", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("+100", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("-+300", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("1", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal(">=", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("++", sts.Get().value);
Assert.Equal(" ", sts.Get().value);
Assert.Equal("!=", sts.Get().value);
Assert.Equal(")", sts.Get().value);
sts.Commit();
Assert.Equal(0, sts.Available());
}
[Fact]
public static void TestParser() {
string program = "(+ 1 (* 2 3))";
StringTokenStream sts = StringTokenStream.generate(program);
Parser p = new Parser(sts);
Assert.Equal(program, string.Format("{0}", p.parse()));
program = "(haskeys o \"i\" \"b\")";
sts = StringTokenStream.generate(program);
p = new Parser(sts);
Assert.Equal(program, string.Format("{0}", p.parse()));
program = "(abc '(1 2 3))";
sts = StringTokenStream.generate(program);
p = new Parser(sts);
Assert.Equal(program, string.Format("{0}", p.parse()));
program = "(abc \"'(1 2 3)\")";
sts = StringTokenStream.generate(program);
p = new Parser(sts);
Assert.Equal(program, string.Format("{0}", p.parse()));
program = """
(begin ;this too
;;; this is a comment
t
)
""";
sts = StringTokenStream.generate(program);
p = new Parser(sts);
Assert.Equal("(begin t)", string.Format("{0}", p.parse()));
}
[Fact]
public static void TestFunctions() {
Executor e = new Executor();
Assert.Equal("(1 2 3)", e.eval("(quote (1 2 3))").ToString());
Assert.Equal("abc", e.eval("(quote abc)").ToString());
Assert.Equal("t", e.eval("(atom 1)").ToString());
Assert.Equal("nil", e.eval("(atom (quote (1 2 3)))").ToString());
Assert.Equal("t", e.eval("(eq 2 2)").ToString());
Assert.Equal("nil", e.eval("(eq 2 3)").ToString());
Assert.Equal("1", e.eval("(car (quote (1 2 3)))").ToString());
Assert.Equal("(2 3)", e.eval("(cdr (quote (1 2 3)))").ToString());
Assert.Equal("(1 . 2)", e.eval("(cons 1 2)").ToString());
Assert.Equal("(1 2)", e.eval("(cons 1 (cons 2 nil))").ToString());
Assert.Equal("(1)", e.eval("(cons 1 nil)").ToString());
Assert.Equal("(1)", e.eval("(cons 1 ())").ToString());
Assert.Equal("\"Case 2\"", e.eval("""
(cond
((eq 1 2) "Case 1")
((eq 2 2) "Case 2"))
""").ToString());
Assert.Equal("\"Case 1\"", e.eval("""
(cond
((eq 2 2) "Case 1")
((eq 2 2) "Case 2"))
""").ToString());
Assert.Equal("nil", e.eval("""
(cond
((eq 1 2) "Case 1")
((eq 3 2) "Case 2"))
""").ToString());
Assert.Equal("t", e.eval("((lambda (a) (eq a a)) 2)").ToString());
Assert.Equal("t", e.eval("(begin (car (quote (nil 1))) t)").ToString());
Assert.Equal("(1)", e.eval("(begin t (cdr (quote (nil 1))))").ToString());
Assert.Equal("t", e.eval("""
(begin
(define abc 10)
(eq abc abc))
""").ToString());
Assert.Equal("1", e.eval("""
(begin
(define if (lambda (condition a b) (
cond (condition a) (t b))))
(if (> 2 1) (car (quote (1 2 3))) (cdr (quote (2 3 4)))))
""").ToString());
Assert.Equal("(3 4)", e.eval("""
(begin
(define if (lambda (condition a b) (
cond (condition a) (t b))))
(if (> 0 1) (car (quote (1 2 3))) (cdr (quote (2 3 4)))))
""").ToString());
Assert.Equal("a", e.eval("'a").ToString());
}
[Fact]
public static void TestFunctionsAdvanced() {
Executor e = new Executor();
Assert.Equal("2", e.eval("""
((lambda (b) b) (car (quote (2 3))))
""").ToString());
Assert.Equal("(3 4 5)", e.eval("""
((lambda (x y . z) z) 1 2 3 4 5)
""").ToString());
Assert.Equal("3", e.eval("""
(begin
(define if (lambda (condition a b) (cond (condition a) (t b))))
(if (< 1 2) 3 2))
""").ToString());
Assert.Equal("2", e.eval("""
(begin
(define if (lambda (condition a b) (cond (condition a) (t b))))
(if (> 1 2) 3 2))
""").ToString());
Assert.Equal("1", e.eval("""
(begin
(define if (lambda* (condition a b) (
cond ((eval condition) (eval a)) (t (eval b)))))
(if (> 2 1) (car (quote (1 2 3))) (cdr (quote (2 3 4)))))
""").ToString());
Assert.Equal("(3 4)", e.eval("""
(begin
(define if (lambda* (condition a b) (
cond ((eval condition) (eval a)) (t (eval b)))))
(if (> 0 1) (car (quote (1 2 3))) (cdr (quote (2 3 4)))))
""").ToString());
Assert.Equal("120", e.eval("""
(begin
(define f (lambda (n) (cond ((<= n 1) 1) (t (* n (f (- n 1)))))))
(f 5))
""").ToString());
Assert.Equal("120", e.eval("""
(begin
(define if (lambda* (condition a b) (
cond ((eval condition) (eval a)) (t (eval b)))))
(define f (lambda (n) (if (<= n 1) 1 (* n (f (- n 1))))))
(f 5))
""").ToString());
Assert.Equal("(1 2 3 4 5)", e.eval("""
(begin
(define if (lambda* (condition a b) (
cond ((eval condition) (eval a)) (t (eval b)))))
((lambda (. args) args) 1 2 3 4 5))
""").ToString());
Assert.Equal("t", e.eval("""
(begin
(define null (lambda* (x) (
cond ((eval x) nil) (t t))))
(null nil))
""").ToString());
Assert.Equal("nil", e.eval("""
(begin
(define null (lambda* (x) (cond ((eval x) nil) (t t))))
(null (quote (1 2))))
""").ToString());
}
[Fact]
public static void ObjectTest() {
Executor e = new Executor();
Expression r;
e.environment.Set("o", Lisp_Object.FromBase(new O(5, false)));
r = e.eval("""(haskeys o "i" "b")""");
Assert.True(((Lisp_Boolean)r).Value());
r = e.eval("""(getitems o "i" "b")""");
Assert.Equal("(5 nil)", string.Format("{0}", r));
r = e.eval("""(invoke o "I" nil)""");
Assert.Equal("5", string.Format("{0}", r));
r = e.eval("""(invoke-generic o "G" nil ((lambda (. args) args) "System.String"))""");
Assert.Equal("\"System.String\"", string.Format("{0}", r));
}
[Fact]
public static void GlobalVariableTest() {
Executor e = new Executor();
e.environment.Set("*o*", new Lisp_Integer(5));
Assert.Equal("10", e.eval("(* *o* 2)").ToString());
}
[Fact]
public static void DefaultEnvironmentTest() {
Executor e = new Executor(new DefaultEnvironment());
Assert.Equal("1", e.eval("(if nil 0 1)").ToString());
Assert.Equal("0", e.eval("(if t 0 1)").ToString());
Assert.Equal("5", e.eval("(if t (if t 5 nil) nil)").ToString());
Assert.Equal("nil", e.eval("(if t (if nil 5 nil) nil)").ToString());
Assert.Equal("(1 2 3)", e.eval("(list 1 2 3)").ToString());
Assert.Equal("3", e.eval("(find 3 (list 1 2 3 4))").ToString());
Assert.Equal("nil", e.eval("(find 0 (list 1 2 3 4))").ToString());
Assert.Equal("(2 4 6)", e.eval("(map (lambda (x) (* x 2)) (quote (1 2 3)))").ToString());
Assert.Equal("nil", e.eval("(and 1 2 3 nil)").ToString());
Assert.Equal("t", e.eval("(and t t t t)").ToString());
Assert.Equal("t", e.eval("(or nil nil t nil)").ToString());
Assert.Equal("nil", e.eval("(or nil nil nil nil)").ToString());
Assert.Equal("t", e.eval("(any (lambda (x) (= x 2)) (list 1 2 3 4 5 6))").ToString());
Assert.Equal("nil", e.eval("(any (lambda (x) (= x 2)) (list 1 3 4 5 6))").ToString());
Assert.Equal("nil", e.eval("(any (lambda (x) (= x 2)) nil)").ToString());
Assert.Equal("t", e.eval("(all (lambda (x) (= 1 (% x 2))) (list 1 3 5))").ToString());
Assert.Equal("nil", e.eval("(all (lambda (x) (= 1 (% x 2))) (list 1 3 4 5))").ToString());
Assert.Equal("nil", e.eval("(all (lambda (x) (= x 2)) nil)").ToString());
Assert.Equal("10", e.eval("(fold (lambda (a b) (+ a b)) 0 (list 1 2 3 4))").ToString());
Assert.Equal("(2 3 4 5 6 7)", e.eval("(append (list 2 3 4) (list 5 6 7))").ToString());
Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort (lambda (a b) (> a b)) (list 5 4 7 3 2 6 1))").ToString());
//Assert.Equal("", e.eval("(rand)").ToString());
//Assert.Equal("", e.eval("(shuf (list 0 1 2 3 4 5 6))").ToString());
Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort (lambda (a b) (> a b)) '(5 4 7 3 2 6 1))").ToString());
Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort > (list 5 4 7 3 2 6 1))").ToString());
}
}
}