jellyfin-smart-playlist/Tests/Tests.cs

192 lines
7.4 KiB
C#

using Xunit;
using Lisp_Environment = Jellyfin.Plugin.SmartPlaylist.Lisp.Environment;
using Lisp_Boolean = Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler.Boolean;
using Lisp_Object = Jellyfin.Plugin.SmartPlaylist.Lisp.Compiler.Object;
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 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(sts.Get().value, "some");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "literal");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "string");
Assert.Equal(sts.Get().value, "\"");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "def");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "ghj");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "+");
Assert.Equal(sts.Get().value, "100");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "-");
Assert.Equal(sts.Get().value, "+");
Assert.Equal(sts.Get().value, "300");
Assert.Equal(sts.Get().value, " ");
Assert.Equal(sts.Get().value, "1");
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, " ");
Assert.Equal(sts.Get().value, "!");
Assert.Equal(sts.Get().value, "=");
Assert.Equal(sts.Get().value, ")");
sts.Commit();
Assert.Equal(sts.Available(), 0);
}
[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 = "(* 2.4 2)";
//sts = StringTokenStream.generate(program);
//p = new Parser(sts);
//Assert.Equal(program, p.parse().ToString());
}
[Fact]
public static void TestFunctions() {
IList<Tuple<string, Expression>> cases = new List<Tuple<string, Expression>>();
Expression e = new Executor().eval("(+ 10 20)");
Assert.Equal(((Integer) e).value, 30);
e = new Executor().eval("(> 1 2)");
Assert.Equal(((Lisp_Boolean) e).value, false);
e = new Executor().eval("(if (> 1 2) 3 4)");
Assert.Equal(((Integer) e).value, 4);
e = new Executor().eval("(begin (define x 1) x)");
Assert.Equal(((Integer) e).value, 1);
e = new Executor().eval("(apply + (1 2))");
Assert.Equal(((Integer) e).value, 3);
e = new Executor().eval("(car (list 10 20 30))");
Assert.Equal(((Integer) e).value, 10);
e = new Executor().eval("(cdr (list 10 20 30))");
Assert.Equal(string.Format("{0}", e), "(20 30)");
e = new Executor().eval("(cons 1 3)");
Assert.Equal(string.Format("{0}", e), "(1 3)");
e = new Executor().eval("(cons 1 (list 2 3))");
Assert.Equal(string.Format("{0}", e), "(1 2 3)");
e = new Executor().eval("(length (cons 1 (list 2 3)))");
Assert.Equal(string.Format("{0}", e), "3");
e = new Executor().eval("(>= 2 2)");
Assert.Equal(string.Format("{0}", e), "t");
e = new Executor().eval("(> 2 2))");
Assert.Equal(string.Format("{0}", e), "nil");
e = new Executor().eval("(and 2 3 4)");
Assert.Equal("4", e.ToString());
e = new Executor().eval("(and 2 nil 4)");
Assert.Equal("nil", e.ToString());
e = new Executor().eval("(or 2 nil 4)");
Assert.Equal("2", e.ToString());
e = new Executor().eval("(or nil 4)");
Assert.Equal("4", e.ToString());
e = new Executor().eval("(= (list 1 2) (list 1 2))");
Assert.Equal(e.ToString(), "t");
e = new Executor().eval("(= (list 1 2 3) (list 1 2))");
Assert.Equal(e.ToString(), "nil");
}
[Fact]
public static void ObjectTest() {
Executor e = new Executor();
Expression r;
e.environment.Set("o", new Lisp_Object(new O(5, false)));
r = e.eval("(haskeys o 'i' 'b')");
Assert.Equal(((Lisp_Boolean)r).value, true);
r = e.eval("(getitems o 'i' 'b')");
Assert.Equal(string.Format("{0}", r), "(5 nil)");
}
[Fact]
public static void ScalarTest() {
Executor e = new Executor();
Expression r;
r = e.eval("(* 2 2)");
Assert.Equal("4", r.ToString());
}
[Fact]
public static void ProcedureTest() {
Executor e = new Executor();
Expression r;
r = e.eval("((lambda (a) (* a a)) 2)");
Assert.Equal(string.Format("{0}", r), "4");
r = e.eval("(begin (define mull (lambda (a) (* a a))) (mull 3))");
Assert.Equal(string.Format("{0}", r), "9");
r = e.eval("(begin (define fact (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1)))))) (fact 10))");
Assert.Equal(string.Format("{0}", r), "3628800");
r = e.eval("(begin (define find (lambda (item list) (if (= list ()) nil (if (= item (car list)) (car list) (find item (cdr list)))))) (find 3 (list 1 2 3 4)))");
Assert.Equal(string.Format("{0}", r), "3");
e = new Executor();
r = e.eval("(begin (define find (lambda (item list) (if (= list ()) nil (if (= item (car list)) (car list) (find item (cdr list)))))) (find 0 (list 1 2 3 4)))");
Assert.Equal(string.Format("{0}", r), "nil");
e = new Executor();
r = e.eval(@"
(begin
(define map (lambda (fc l) (if (= l ()) () (cons (fc (car l)) (map fc (cdr l))))))
(define multwo (lambda (x) (* 2 x)))
(map multwo (list 1 2 3)))
");
Assert.Equal(string.Format("{0}", r), "(2 4 6)");
}
[Fact]
public static void DefaultEnvironmentTest() {
Executor e = new Executor(new DefaultEnvironment());
Assert.Equal("nil", e.eval("(find 0 (list 1 2 3 4))").ToString());
Assert.Equal("3", e.eval("(find 3 (list 1 2 3 4))").ToString());
}
}
}