#!/bin/bash trap "exit 130" INT cleanup() { rm -f err noequals*.ini test.ini ltest.ini good.ini example.ini; exit; } trap cleanup EXIT export PATH=..:$PATH test=0 fail() { test=$(($test+1)); echo "Test $test FAIL (line ${BASH_LINENO[0]})"; exit 1; } ok() { test=$(($test+1)); echo "Test $test OK (line ${BASH_LINENO[0]})"; } cp ../example.ini . # invalid params ---------------------------------------- :> test.ini crudini 2>/dev/null && fail crudini --met test.ini 2>/dev/null && fail # bad mode crudini --set 2>/dev/null && fail # no file crudini --set test.ini 2>/dev/null && fail # no section crudini --get 2>/dev/null && fail # no file crudini --get test.ini '' 'name' 'val' 2>/dev/null && fail # value crudini --get --format=bad test.ini 2>/dev/null && fail # bad format crudini --del 2>/dev/null && fail # no file crudini --del test.ini 2>/dev/null && fail # no section crudini --del test.ini '' 'name' 'val' 2>/dev/null && fail # value crudini --merge 2>/dev/null && fail # no file crudini --merge test.ini '' 'name' 2>/dev/null && fail # param crudini --del test.ini '' 'name' 'val' 2>/dev/null && fail # value crudini --get --format=ggg test.ini 2>&1 | grep -q 'format not recognized' || fail crudini --get test.ini 'DEFAULT' missing 2>&1 | grep -q 'Parameter not found' || fail ok # --set ------------------------------------------------- :> test.ini crudini --set test.ini '' name val printf '%s\n' 'name = val' > good.ini diff -u test.ini good.ini && ok || fail :> test.ini crudini --set test.ini DEFAULT name val printf '%s\n' '[DEFAULT]' 'name = val' > good.ini diff -u test.ini good.ini && ok || fail :> test.ini crudini --set test.ini nonDEFAULT name val printf '%s\n' '[nonDEFAULT]' 'name = val' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'global=val' > test.ini crudini --set test.ini '' global valnew printf '%s\n' 'global=valnew' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'global=val' > test.ini crudini --set test.ini DEFAULT global valnew printf '%s\n' '[DEFAULT]' 'global=valnew' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[DEFAULT]' 'global=val' > test.ini crudini --set test.ini DEFAULT global valnew printf '%s\n' '[DEFAULT]' 'global=valnew' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'global=val' '' '[nonDEFAULT]' 'name=val' > test.ini crudini --set test.ini '' global valnew printf '%s\n' 'global=valnew' '' '[nonDEFAULT]' 'name=val' > good.ini diff -u test.ini good.ini && ok || fail # do these --sets which test [DEFAULT] handling also with --inplace for mode in '' '--inplace'; do # Add '[DEFAULT]' if explicitly specified printf '%s\n' 'global=val' '' '[nonDEFAULT]' 'name=val' > test.ini crudini $mode --set test.ini DEFAULT global valnew printf '%s\n' '[DEFAULT]' 'global=valnew' '' '[nonDEFAULT]' 'name=val' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[nonDEFAULT1]' 'name=val' '[nonDEFAULT2]' 'name=val' > test.ini crudini $mode --set test.ini DEFAULT global val printf '%s\n' '[DEFAULT]' 'global = val' '[nonDEFAULT1]' 'name=val' '[nonDEFAULT2]' 'name=val' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[nonDEFAULT1]' 'name=val' '[nonDEFAULT2]' 'name=val' > test.ini crudini $mode --set test.ini '' global val printf '%s\n' 'global = val' '[nonDEFAULT1]' 'name=val' '[nonDEFAULT2]' 'name=val' > good.ini diff -u test.ini good.ini && ok || fail # Ensure '[DEFAULT]' is not duplicated printf '%s\n' '[DEFAULT]' > test.ini crudini $mode --set test.ini DEFAULT global val printf '%s\n' '[DEFAULT]' 'global = val' > good.ini diff -u test.ini good.ini && ok || fail # Ensure '[DEFAULT]' is not duplicated when trailing space is present printf '%s\n' '[DEFAULT] ' > test.ini crudini $mode --set test.ini DEFAULT global val printf '%s\n' '[DEFAULT] ' 'global = val' > good.ini diff -u test.ini good.ini && ok || fail # Ensure '[DEFAULT]' is not duplicated when a trailing comment is present printf '%s\n' '[DEFAULT] #comment' > test.ini crudini $mode --set test.ini DEFAULT global val printf '%s\n' '[DEFAULT] #comment' 'global = val' > good.ini diff -u test.ini good.ini && ok || fail # Maintain colon separation crudini $mode --set example.ini section1 colon val grep -q '^colon:val' example.ini && ok || fail # Maintain space separation crudini $mode --set example.ini section1 nospace val grep -q '^nospace=val' example.ini && ok || fail done # value is optional :> test.ini crudini --set test.ini '' name printf '%s\n' 'name = ' > good.ini diff -u test.ini good.ini && ok || fail # value is optional printf '%s\n' 'name=val' > test.ini crudini --set test.ini '' name printf '%s\n' 'name=' > good.ini diff -u test.ini good.ini && ok || fail # Protect against creating non parseable files (with nested [[]]) :> test.ini crudini --set test.ini '[section]' name val 2>/dev/null && fail test -s test.ini && fail printf '%s\n' '[[section]]' 'name=val' > test.ini crudini --get test.ini '[section]' name 2>/dev/null && fail printf '%s\n' '[section]' '[name=val' > test.ini crudini --get test.ini 'section' '[name' 2>/dev/null && fail printf '%s\n' '[section]' 'n[ame=val' > test.ini test $(crudini --get test.ini 'section' 'n[ame') = 'val' && ok || fail # --existing with file creation for mode in '' '--inplace'; do crudini $mode --set missing.ini '' name val 2>/dev/null && ok || fail rm -f missing.ini for emode in '' 'file' 'section' 'param'; do crudini $mode --existing="$emode" --set missing.ini '' name val \ 2>/dev/null && fail || ok test -f missing.ini && fail done rm -f missing.ini done # --existing[=param] :> test.ini crudini --set test.ini '' gname val crudini --set --existing test.ini '' gname val2 crudini --set --existing=inval test.ini '' gname val3 2>/dev/null && fail crudini --set --existing test.ini '' gname2 val 2>/dev/null && fail crudini --set test.ini section1 name val crudini --set --existing test.ini section1 name val2 crudini --set --existing test.ini section1 name2 val 2>/dev/null && fail printf '%s\n' 'gname = val2' '' '' '[section1]' 'name = val2' > good.ini diff -u test.ini good.ini && ok || fail # --existing=section :> test.ini crudini --set test.ini '' gname val crudini --set --existing='section' test.ini '' gname val2 crudini --set --existing='section' test.ini '' gname2 val 2>/dev/null || fail crudini --set test.ini section1 name val crudini --set --existing='section' test.ini section1 name val2 crudini --set --existing='section' test.ini section1 name2 val 2>/dev/null || fail printf '%s\n' 'gname = val2' 'gname2 = val' \ '' '' '[section1]' 'name = val2' 'name2 = val' > good.ini diff -u test.ini good.ini && ok || fail # --get ------------------------------------------------- # basic get test "$(crudini --get example.ini section1 cAps)" = 'not significant' && ok || fail # get sections crudini --get example.ini > test.ini printf '%s\n' DEFAULT section1 'empty section' non-sh-compat list > good.ini diff -u test.ini good.ini && ok || fail # get implicit default section crudini --get example.ini '' > test.ini printf '%s\n' 'global' > good.ini diff -u test.ini good.ini || fail crudini --format=ini --get example.ini '' > test.ini printf '%s\n' '[DEFAULT]' 'global = supported' > good.ini diff -u test.ini good.ini || fail ok # get explicit default section crudini --get example.ini DEFAULT > test.ini printf '%s\n' 'global' > good.ini diff -u test.ini good.ini || fail crudini --get --format ini example.ini DEFAULT > test.ini printf '%s\n' '[DEFAULT]' 'global = supported' > good.ini diff -u test.ini good.ini || fail ok # get section1 in ini format crudini --format=ini --get example.ini section1 > test.ini diff -u test.ini section1.ini && ok || fail # get section1 in sh format crudini --format=sh --get example.ini section1 > test.ini diff -u test.ini section1.sh && ok || fail # empty DEFAULT is not printed printf '%s\n' '[DEFAULT]' '#comment' '[section1]' > test.ini test "$(crudini --get test.ini)" = 'section1' || fail printf '%s\n' '#comment' '[section1]' > test.ini test "$(crudini --get test.ini)" = 'section1' || fail ok # Ensure we handle comments correctly printf '%s\n' '[DEFAULT]' '#c1' ';c2' '%inc1' > test.ini test "$(crudini --get test.ini)" = '' || fail printf '%s\n' '[section1]' 'remote=1' > test.ini test "$(crudini --get test.ini 'section1')" = 'remote' || fail ok # missing bits :> test.ini crudini --get missing.ini 2>/dev/null && fail test "$(crudini --get test.ini)" = '' || fail crudini --get test.ini '' || fail crudini --get test.ini '' 'missing' 2>/dev/null && fail ok # --merge ----------------------------------------------- # XXX: An empty default section isn't merged :> test.ini printf '%s\n' '[DEFAULT]' '#comment' '[section1]' | crudini --merge test.ini || fail printf '%s\n' '[section1]' > good.ini diff -u test.ini good.ini && ok || fail :> test.ini printf '%s\n' '[DEFAULT]' 'name=val' '[section1]' | crudini --merge test.ini || fail printf '%s\n' '[DEFAULT]' 'name = val' '' '[section1]' > good.ini diff -u test.ini good.ini && ok || fail :> test.ini printf '%s\n' 'name=val' | crudini --merge test.ini || fail printf '%s\n' 'name = val' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name=val1' > test.ini printf '%s\n' 'name = val2' | crudini --merge test.ini || fail printf '%s\n' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[DEFAULT]' 'name=val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge test.ini || fail printf '%s\n' '[DEFAULT]' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name = val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge test.ini '' || fail printf '%s\n' 'name = val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[DEFAULT]' 'name=val1' > test.ini printf '%s\n' '[DEFAULT]' 'name=val2' | crudini --merge test.ini || fail printf '%s\n' '[DEFAULT]' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[DEFAULT]' 'name=val1' > test.ini printf '%s\n' '[DEFAULT]' 'name=val2' | crudini --merge test.ini '' || fail printf '%s\n' '[DEFAULT]' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' '[DEFAULT]' 'name=val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge test.ini '' || fail printf '%s\n' '[DEFAULT]' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name=val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge test.ini DEFAULT || fail printf '%s\n' '[DEFAULT]' 'name=val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name=val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge test.ini new || fail printf '%s\n' 'name=val1' '' '' '[new]' 'name = val2' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name=val1' > test.ini printf '%s\n' 'name=val2' | crudini --merge --existing test.ini new 2>/dev/null && fail || ok printf '%s\n' 'name=val1' > test.ini printf '%s\n' 'name2=val2' | crudini --merge --existing test.ini || fail printf '%s\n' 'name=val1' > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' 'name=val1' '[section1]' 'name=val2' > test.ini printf '%s\n' 'name=val1a' '[section1]' 'name=val2a' | crudini --merge --existing test.ini || fail printf '%s\n' 'name=val1a' '[section1]' 'name=val2a' > good.ini diff -u test.ini good.ini && ok || fail # All input sections merged to a specific section printf '%s\n' 'name=val1' '[section1]' 'name=val2' > test.ini printf '%s\n' 'name=val2a' '[section2]' 'name2=val' | crudini --merge test.ini 'section1' || fail printf '%s\n' 'name=val1' '[section1]' 'name=val2a' 'name2 = val' > good.ini diff -u test.ini good.ini && ok || fail # Maintain case for existing parameters printf '%s\n' '[section]' 'name=val' > test.ini printf '%s\n' '[section]' 'Name=val' | crudini --merge test.ini || fail printf '%s\n' '[section]' 'name=val'> good.ini diff -u test.ini good.ini && ok || fail # Honor case for new parameters (spacing not currently honored) printf '%s\n' '[section]' 'name1=val' > test.ini printf '%s\n' '[section]' 'Name2=val' | crudini --merge test.ini || fail printf '%s\n' '[section]' 'name1=val' 'Name2 = val' > good.ini diff -u test.ini good.ini && ok || fail # Note iniparse currently matches sections case insensitively printf '%s\n' '[section1]' 'name=val1' > test.ini printf '%s\n' '[Section1]' 'name=val2' | crudini --merge --existing 2>/dev/null test.ini && fail || ok printf '%s\n' '[Section1]' 'name=val2' | crudini --merge test.ini || fail printf '%s\n' '[section1]' 'name=val1' '' '' '[Section1]' 'name = val2' > good.ini diff -u test.ini good.ini && ok || fail # --del ------------------------------------------------- for sec in '' '[DEFAULT]'; do printf '%s\n' $sec 'name = val' > test.ini crudini --del test.ini '' noname || fail crudini --del --existing test.ini '' noname 2>/dev/null && fail crudini --del test.ini '' name || fail :> good.ini [ "$sec" ] && printf '%s\n' $sec > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' $sec 'name = val' > test.ini crudini --del test.ini 'DEFAULT' noname || fail crudini --del --existing test.ini 'DEFAULT' noname 2>/dev/null && fail crudini --del test.ini 'DEFAULT' name || fail :> good.ini [ "$sec" ] && printf '%s\n' $sec > good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' $sec 'name = val' > test.ini crudini --del test.ini nosect || fail crudini --del --existing=file test.ini nosect || fail crudini --del --existing=section test.ini nosect 2>/dev/null && fail crudini --del --existing=param test.ini '' noname 2>/dev/null && fail crudini --del --existing test.ini nosect 2>/dev/null 2>/dev/null && fail crudini --del --existing=param test.ini '' name || fail crudini --del test.ini '' || fail :> good.ini diff -u test.ini good.ini && ok || fail printf '%s\n' $sec 'name = val' > test.ini crudini --del test.ini nosect || fail crudini --del --existing=file test.ini nosect || fail crudini --del --existing=section test.ini nosect 2>/dev/null && fail crudini --del --existing=param test.ini 'DEFAULT' noname 2>/dev/null && fail crudini --del --existing test.ini nosect 2>/dev/null && fail crudini --del test.ini 'DEFAULT' || fail :> good.ini diff -u test.ini good.ini && ok || fail done # --del non existing sections/params shouldn't give an error printf '%s\n' '[section]' 'name = val' > test.ini crudini --verbose --del test.ini nosect 2>&1 | grep -q ^unchanged || fail crudini --verbose --del test.ini nosect noname 2>&1 | grep -q ^unchanged || fail crudini --verbose --del test.ini section noname 2>&1 | grep -q ^unchanged || fail crudini --verbose --del test.ini section noname 2>&1 | grep -q ^unchanged || fail crudini --verbose --del --list test.ini section noname val 2>&1 | grep -q ^unchanged || fail crudini --verbose --del --list test.ini nosect noname val 2>&1 | grep -q ^unchanged || fail crudini --verbose --del test.ini section 2>&1 | grep -q ^changed || fail test -s test.ini && fail || ok # --del non existing file shouldn't create an empty file crudini --verbose --del missing.ini section 2>&1 | grep -q ^unchanged || fail crudini --existing --del missing.ini section 2>/dev/null && fail test -f missing.ini && fail || ok # --get-lines -------------------------------------------- crudini --get --format=lines example.ini section1 > test.ini || fail diff -u test.ini section1.lines && ok || fail crudini --get --format=lines example.ini > test.ini || fail diff -u test.ini example.lines && ok || fail # --list ------------------------------------------------- # Add new item to list crudini --list --set example.ini list list1 v3 || fail test "$(crudini --get example.ini list list1)" = 'v1, v2, v3' && ok || fail # Ensure item in list crudini --list --set example.ini list list1 v3 || fail test "$(crudini --get example.ini list list1)" = 'v1, v2, v3' && ok || fail # Delete item from list crudini --list --del example.ini list list1 v3 || fail test "$(crudini --get example.ini list list1)" = 'v1, v2' && ok || fail # Delete non existing item from list for existing in '' '--existing'; do crudini $existing --list --del example.ini list list1 v3 || fail test "$(crudini --get example.ini list list1)" = 'v1, v2' && ok || fail done # Add new item to list without spacing # auto crudini --list --set example.ini list list2 v3 || fail test "$(crudini --get example.ini list list2)" = 'v1,v2,v3' && ok || fail crudini --set example.ini list list2 'v1,v2' || fail # explicit crudini --list --list-sep=, --set example.ini list list2 v3 || fail test "$(crudini --get example.ini list list2)" = 'v1,v2,v3' && ok || fail # Delete item from list without spacing # auto crudini --list --del example.ini list list2 v3 || fail test "$(crudini --get example.ini list list2)" = 'v1,v2' && ok || fail crudini --set example.ini list list2 'v1,v2,v3' || fail # explicit crudini --list --list-sep=, --del example.ini list list2 v3 || fail test "$(crudini --get example.ini list list2)" = 'v1,v2' && ok || fail # Delete honoring --existing crudini --list --existing --del example.ini nolist list1 v3 2>/dev/null && fail || ok crudini --list --existing --del example.ini list nolist1 v3 2>/dev/null && fail || ok # support parsing from stdin test "$(printf '%s\n' global=1 | crudini --get - '' global)" = 1 && ok || fail # --verbose printf '%s\n' '[section]' 'param = value' > test.ini crudini --verbose --set test.ini section param value 2>&1 | grep -q ^unchanged && ok || fail crudini --verbose --set test.ini section param valuE 2>&1 | grep -q ^changed && ok || fail crudini --verbose --del test.ini section param 2>&1 | grep -q ^changed && ok || fail crudini --verbose --del test.ini section param 2>&1 | grep -q ^unchanged && ok || fail crudini --verbose --del test.ini section $'multiline\nchanged:' 2>&1 | grep -q ^changed && fail || ok # ensure leading blank lines maintained with global settings printf '%s\n' '' 'option=1' > file.conf printf '%s\n' '' 'option=2' > good.conf crudini --set file.conf '' option 2 || fail diff -u good.conf file.conf && ok || fail rm file.conf good.conf # ensure errors diagnosed correctly crudini --get example.ini 2>err | : ! test -s err && ok || fail #EPIPE ignored if test -e /dev/full; then crudini --get example.ini 2>err >/dev/full grep -q 'No space left' err && ok || fail fi # ensure symlinks handled correctly in file replace mode printf '%s\n' '[section]' 'param = value' > test.ini ln -s test.ini ltest.ini crudini --set ltest.ini section param newvalue || fail test "$(crudini --get test.ini section param)" = 'newvalue' && ok || fail crudini --output=ltest.ini --set ltest.ini section param newvalue2 || fail test "$(crudini --get test.ini section param)" = 'newvalue2' && ok || fail # Test single token parameters (without equals) cp ../noequals.ini . crudini --get noequals.ini >/dev/null && ok || fail cp noequals.ini noequals_new.ini printf '%s\n' 'new' 'new_equals = ' >> noequals_new.ini for param in param{1..3} colon{1..2} new; do crudini --set noequals.ini noequals $param || fail done crudini --set noequals.ini noequals new_equals '' || fail diff -u noequals.ini noequals_new.ini && ok || fail # Test can read windows format files printf '%s\r\n' '' 'param = value' > test.ini crudini --get test.ini DEFAULT param > /dev/null || fail