-updated liquidsoap scripts + library to be liquidsoap-beta2 compliant
This commit is contained in:
parent
022b013dd2
commit
3dc1380fab
24 changed files with 593 additions and 192 deletions
21
python_apps/pypo/liquidsoap_scripts/library/tests/BUG403.liq
Normal file
21
python_apps/pypo/liquidsoap_scripts/library/tests/BUG403.liq
Normal file
|
@ -0,0 +1,21 @@
|
|||
# This is the test for bug #403 from our old trac.
|
||||
#
|
||||
# Make a switch() declare itself ready and arrange to use it for the next
|
||||
# frame where it isn't ready anymore.
|
||||
#
|
||||
# Two switches A and B
|
||||
# A is only ready for a short period of time due to its predicates.
|
||||
# B reselects at the end of a frame just before A becomes unavailable
|
||||
# as a result, B has selected = A, attempts to stream it
|
||||
# but A finds itself not ready anymore.
|
||||
# In other words, B committed but A did not.
|
||||
|
||||
r = ref false
|
||||
pred = { v=!r ; r:=false ; v }
|
||||
add_timeout(2.,{ r := true ; (-1.) })
|
||||
|
||||
mixer = fallback(id="mixer", track_sensitive=false,
|
||||
[at(pred, sine(duration=3.)), blank()])
|
||||
|
||||
output.dummy(mixer)
|
||||
add_timeout(3.,{ print("TEST PASSED") ; shutdown() ; (-1.) })
|
10
python_apps/pypo/liquidsoap_scripts/library/tests/LS268.liq
Normal file
10
python_apps/pypo/liquidsoap_scripts/library/tests/LS268.liq
Normal file
|
@ -0,0 +1,10 @@
|
|||
# In LS-268 we realized that an incorrect assumption had
|
||||
# been made in code from LS-394, resulting in a crash in
|
||||
# case of source re-awakening.
|
||||
|
||||
p = input.http("http://localhost:8000/nonexistent")
|
||||
o = output.dummy(fallible=true,p)
|
||||
|
||||
add_timeout(2.,{ source.shutdown(o) ; (-1.) })
|
||||
add_timeout(3.,{ output.dummy(fallible=true,p) ; (-1.) })
|
||||
add_timeout(4.,{ shutdown() ; (-1.) })
|
11
python_apps/pypo/liquidsoap_scripts/library/tests/LS354-1.liq
Executable file
11
python_apps/pypo/liquidsoap_scripts/library/tests/LS354-1.liq
Executable file
|
@ -0,0 +1,11 @@
|
|||
s = on_track(
|
||||
fun(_)-> begin print("TEST PASSED") shutdown() end,
|
||||
blank(duration=1.))
|
||||
|
||||
r = ref false
|
||||
d = source.dynamic({ if !r then [s] else [] end })
|
||||
|
||||
output.dummy(mksafe(d))
|
||||
|
||||
add_timeout(2.,{r:=true;(-1.)})
|
||||
add_timeout(4.,{print("TEST FAILED");shutdown();(-1.)})
|
15
python_apps/pypo/liquidsoap_scripts/library/tests/LS354-2.liq
Executable file
15
python_apps/pypo/liquidsoap_scripts/library/tests/LS354-2.liq
Executable file
|
@ -0,0 +1,15 @@
|
|||
s1 = fail()
|
||||
s2 = on_track(
|
||||
fun(_)-> begin print("TEST PASSED") shutdown() end,
|
||||
blank(duration=1.))
|
||||
|
||||
r = ref 0
|
||||
d = source.dynamic({ if !r==1 then [s1]
|
||||
elsif !r==2 then [s2]
|
||||
else [] end })
|
||||
|
||||
output.dummy(mksafe(d))
|
||||
|
||||
add_timeout(2.,{r:=1;(-1.)})
|
||||
add_timeout(3.,{r:=2;(-1.)})
|
||||
add_timeout(5.,{print("TEST FAILED");shutdown();(-1.)})
|
17
python_apps/pypo/liquidsoap_scripts/library/tests/LS460.liq
Normal file
17
python_apps/pypo/liquidsoap_scripts/library/tests/LS460.liq
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Scenario:
|
||||
# Let foo start using q, then stop it, skip in q.
|
||||
# When foo restarts it doesn't know that q isn't ready anymore,
|
||||
# which can lead to a crash.
|
||||
|
||||
q = once(sine(duration=10.))
|
||||
output.dummy(id="bar",mksafe(q))
|
||||
output.dummy(id="foo",fallback([amplify(1.,q),blank(duration=1.)]))
|
||||
|
||||
def at(t,s)
|
||||
add_timeout(t,{ignore(server.execute(s));(-1.)})
|
||||
end
|
||||
|
||||
at(3.,"foo.stop")
|
||||
at(4.,"bar.skip")
|
||||
at(5.,"foo.start")
|
||||
add_timeout(6.,{print("TEST PASSED");shutdown();(-1.)})
|
13
python_apps/pypo/liquidsoap_scripts/library/tests/LS503.liq
Normal file
13
python_apps/pypo/liquidsoap_scripts/library/tests/LS503.liq
Normal file
|
@ -0,0 +1,13 @@
|
|||
# In LS-503 we realized that a source may throw an
|
||||
# exception during output_get_ready call in the initial
|
||||
# main phase. This code reproduces the issue by throwing
|
||||
# an exception in output.icecast.
|
||||
|
||||
# Reopen stderr to /dev/null to
|
||||
# disable printing expected exception
|
||||
reopen.stderr("/dev/null")
|
||||
|
||||
p = input.http("http://localhost:8000/nonexistent")
|
||||
o = output.icecast(%wav,fallible=true,host="nonexistent",
|
||||
mount="test",p)
|
||||
|
16
python_apps/pypo/liquidsoap_scripts/library/tests/Makefile
Normal file
16
python_apps/pypo/liquidsoap_scripts/library/tests/Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
DISTFILES = Makefile $(wildcard *.liq) $(wildcard *.pl)
|
||||
|
||||
top_srcdir = ../..
|
||||
include $(top_srcdir)/Makefile.rules
|
||||
|
||||
test:
|
||||
@for i in $(wildcard *.liq) ; do \
|
||||
echo -n "$$i... " ; $(top_srcdir)/src/liquidsoap -q - < ./$$i | head -n 1 ; \
|
||||
done
|
||||
@echo -n "type_errors.pl... " ; \
|
||||
if (./type_errors.pl > /dev/null 2> /dev/null) ; then \
|
||||
echo "TEST PASSED (check manually the prettiness of messages)" ; \
|
||||
else \
|
||||
echo "TEST FAILED" ; \
|
||||
fi
|
43
python_apps/pypo/liquidsoap_scripts/library/tests/eval.liq
Normal file
43
python_apps/pypo/liquidsoap_scripts/library/tests/eval.liq
Normal file
|
@ -0,0 +1,43 @@
|
|||
count = ref 1
|
||||
fail = ref false
|
||||
|
||||
def echo(s)
|
||||
# system("echo "^quote(s))
|
||||
if s != string_of(!count) then
|
||||
fail := true
|
||||
end
|
||||
count := !count + 1
|
||||
()
|
||||
end
|
||||
|
||||
def test(lbl,f)
|
||||
if f() then echo(lbl) else echo("fail "^lbl) end
|
||||
end
|
||||
|
||||
test("1",{ 1==1 })
|
||||
test("2",{ 1+1==2 })
|
||||
test("3",{ (-1)+2==1 })
|
||||
test("4",{ (-1)+2 <= 3*2 })
|
||||
test("5",{ true })
|
||||
test("6",{ true and true })
|
||||
test("7",{ 1==1 and 1==1 })
|
||||
test("8",{ (1==1) and (1==1) })
|
||||
test("9",{ true and (-1)+2 <= 3*2 })
|
||||
|
||||
l = [ ("bla",""), ("bli","x"), ("blo","xx"), ("blu","xxx"), ("dix","10") ]
|
||||
echo(l["dix"])
|
||||
test("11",{ 2 == list.length(string.split(separator="",l["blo"])) })
|
||||
|
||||
%ifdef foobarbaz
|
||||
if = if is not a well-formed expression, and we do not care...
|
||||
%endif
|
||||
|
||||
echo("1#{1+1}")
|
||||
echo(string_of(int_of_float(float_of_string(default=13.,"blah"))))
|
||||
|
||||
f=fun(x)->x
|
||||
# Checking that the following is not recursive:
|
||||
f=fun(x)->f(x)
|
||||
echo(string_of(f(14)))
|
||||
|
||||
if !fail then print("TEST FAILED") else print("TEST PASSED") end
|
82
python_apps/pypo/liquidsoap_scripts/library/tests/type_errors.pl
Executable file
82
python_apps/pypo/liquidsoap_scripts/library/tests/type_errors.pl
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
use strict ;
|
||||
|
||||
my $liquidsoap = "../../src/liquidsoap";
|
||||
die unless -f $liquidsoap ;
|
||||
|
||||
$liquidsoap = "$liquidsoap -c";
|
||||
|
||||
sub section {
|
||||
print "\n*** $_[0] ***\n\n" ;
|
||||
}
|
||||
|
||||
sub incorrect {
|
||||
my $expr = pop ;
|
||||
print "Incorrect expression $expr...\n" ;
|
||||
system "$liquidsoap '$expr'" ;
|
||||
die unless (($?>>8)==1) ;
|
||||
print "\n" ;
|
||||
}
|
||||
|
||||
sub correct {
|
||||
my $expr = pop ;
|
||||
print "Correct expression $expr...\n" ;
|
||||
system "$liquidsoap -i '$expr'" ;
|
||||
die unless (($?>>8)==0) ;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
section("BASIC");
|
||||
incorrect('[1]==["1"]');
|
||||
incorrect('1==["1"]');
|
||||
incorrect('1==(1,"1")');
|
||||
# In some of those examples the type error could be reported for a
|
||||
# sub-expression since we have location information.
|
||||
# With the concise error, it's still pretty good currently.
|
||||
incorrect('(1,1)==(1,"1")');
|
||||
incorrect('(1,1)==("1",1)');
|
||||
incorrect('1==request.create("")');
|
||||
incorrect('fun(x)->x(snd(x))');
|
||||
|
||||
section("SUBTYPING");
|
||||
incorrect('(1:unit)');
|
||||
correct('((blank():source(1,1,1)):source(*,*,*))');
|
||||
incorrect('((blank():source(*,*,*)):source(1,1,1))');
|
||||
# Next one requires the inference of a subtype (fixed vs. variable arity)
|
||||
correct('audio_to_stereo(add([]))');
|
||||
|
||||
section("CONSTRAINTS");
|
||||
incorrect('"bl"+"a"');
|
||||
incorrect('(fun(a,b)->a+b)==(fun(a,b)->a+b)');
|
||||
incorrect('fun(x)->x(x)'); # TODO is it an accident that we get same varname
|
||||
incorrect('def f(x) y=snd(x) y(x) end');
|
||||
|
||||
section("LET GENERALIZATION");
|
||||
correct('def f(x) = y=x ; y end f(3)+snd(f((1,2)))');
|
||||
incorrect('def f(x) = y=x ; y end f(3)+"3"');
|
||||
|
||||
section("ARGUMENTS");
|
||||
# The errors should be about the type of the param, not of the function.
|
||||
incorrect('1+"1"');
|
||||
# Also, a special simple error is expected for obvious labelling mistakes.
|
||||
incorrect('fallback(transitions=[],xxxxxxxxxxx=[])');
|
||||
incorrect('fallback(transitions=[],transitions=[])');
|
||||
|
||||
section("FUNCTIONS");
|
||||
incorrect('fallback(transitions=[fun(~l)->1])');
|
||||
incorrect('fallback(transitions=[fun(~l=1)->1])');
|
||||
incorrect('fallback(transitions=[fun(x,y=blank())->y])');
|
||||
incorrect('fallback(transitions=[fun(x,y)->0])');
|
||||
correct('f=fallback(transitions=[fun(x,y,a=2)->x])');
|
||||
incorrect('fallback(transitions=[fun(x,y)->y+1])');
|
||||
correct('x=fun(f)->f(3) y=x(fun(f,u="1")->u)');
|
||||
|
||||
section("CONTENT KIND");
|
||||
incorrect('output.file(%vorbis(stereo),"foo",mean(blank()))');
|
||||
incorrect('output.file(%vorbis(stereo),"foo",video.add_image(blank()))');
|
||||
incorrect('def f(x) = output.file(%vorbis(stereo),"",x) output.file(%vorbis(mono),"",x) end');
|
||||
incorrect('add([output.file(%vorbis(stereo),"",blank()),output.file(%vorbis(mono),"",blank())])');
|
||||
incorrect('add([mean(blank()),audio_to_stereo(add([]))])');
|
||||
|
||||
print "Everything's good!\n" ;
|
112
python_apps/pypo/liquidsoap_scripts/library/tests/typing.liq
Normal file
112
python_apps/pypo/liquidsoap_scripts/library/tests/typing.liq
Normal file
|
@ -0,0 +1,112 @@
|
|||
# Check these examples with: liquidsoap --no-libs -i -c typing.liq
|
||||
|
||||
# TODO Throughout this file, parsing locations displayed in error messages
|
||||
# are often much too inaccurate.
|
||||
|
||||
# Check that some polymorphism is allowed.
|
||||
# id : (string,'a)->'a
|
||||
def id(a,b)
|
||||
log(a)
|
||||
b
|
||||
end
|
||||
ignore("bla"==id("bla","bla"))
|
||||
ignore(0==id("zero",0))
|
||||
|
||||
# Reporting locations for the next error is non-trivial, because it is about
|
||||
# an instantiation of the type of id. The deep error doesn't have relevant
|
||||
# information about why the int should be a string, the outer one has.
|
||||
# id(0,0)
|
||||
|
||||
# Polymorphism is limited to outer generalizations, this is not system F.
|
||||
# apply : ((string)->'a)->'a
|
||||
def apply(f)
|
||||
f("bla")
|
||||
# f is not polymorphic, the following is forbidden:
|
||||
# f(0)
|
||||
# f(f)
|
||||
end
|
||||
|
||||
# The level checks forbid abusive generalization.
|
||||
# id' : ('a)->'a
|
||||
def id'(x)
|
||||
# If one isn't careful about levels/scoping, f2 gets the type ('a)->'b
|
||||
# and so does twisted_id.
|
||||
def f2(y)
|
||||
x
|
||||
end
|
||||
f2(x)
|
||||
end
|
||||
|
||||
# More errors...
|
||||
# 0=="0"
|
||||
# [3,""]
|
||||
|
||||
# Subtyping, functions and lists.
|
||||
f1 = fun () -> 3
|
||||
f2 = fun (a=1) -> a
|
||||
|
||||
# This is OK, l1 is a list of elements of type f1.
|
||||
l1 = [f1,f2]
|
||||
list.iter(fun (f) -> log(string_of(f())), l1)
|
||||
# Forbidden. Indeed, f1 doesn't accept any argument -- although f2 does.
|
||||
# Here the error message may even be too detailed since it goes back to the
|
||||
# definition of l1 and requires that f1 has type (int)->int.
|
||||
# list.iter(fun (f) -> log(string_of(f(42))), l1)
|
||||
|
||||
# Actually, this is forbidden too, but the reason is more complex...
|
||||
# The infered type for the function is ((int)->int)->unit,
|
||||
# and (int)->int is not a subtype of (?int)->int.
|
||||
# There's no most general answer here since (?int)->int is not a
|
||||
# subtype of (int)->int either.
|
||||
# list.iter(fun (f) -> log(string_of(f(42))), [f2])
|
||||
|
||||
# Unlike l1, this is not OK, since we don't leave open subtyping constraints
|
||||
# while infering types.
|
||||
# I hope we can make the inference smarter in the future, without obfuscating
|
||||
# the error messages too much.
|
||||
# The type error here shows the use of all the displayed positions:
|
||||
# f1 has type t1, f2 has type t2, t1 should be <: t2
|
||||
# l2 = [ f2, f1 ]
|
||||
|
||||
# An error where contravariance flips the roles of both sides..
|
||||
# [fun (x) -> x+1, fun (y) -> y^"."]
|
||||
|
||||
# An error without much locations..
|
||||
# TODO An explaination about the missing label would help a lot here.
|
||||
# def f(f)
|
||||
# f(output.icecast.vorbis)
|
||||
# f(output.icecast.mp3)
|
||||
# end
|
||||
|
||||
# This causes an occur-check error.
|
||||
# TODO The printing of the types breaks the sharing of one EVAR
|
||||
# across two types. Here the sharing is actually the origin of the occur-check
|
||||
# error. And it's not easy to understand..
|
||||
# omega = fun (x) -> x(x)
|
||||
|
||||
# Now let's test ad-hoc polymorphism.
|
||||
|
||||
echo = fun(x) -> system("echo #{quote(string_of(x))}")
|
||||
|
||||
ignore("bla")
|
||||
ignore((1,3.12))
|
||||
ignore(1 + 1)
|
||||
ignore(1. + 2.14)
|
||||
|
||||
# string is not a Num
|
||||
# echo("bl"+"a")
|
||||
|
||||
ignore(1 <= 2)
|
||||
ignore((1,2) == (1,3))
|
||||
|
||||
# float <> int
|
||||
# echo(1 == 2.)
|
||||
|
||||
# source is not an Ord
|
||||
# echo(blank()==blank())
|
||||
|
||||
def sum_eq(a,b)
|
||||
a+b == a
|
||||
end
|
||||
|
||||
print("TEST PASSED")
|
Loading…
Add table
Add a link
Reference in a new issue