Fossil

Check-in [42a07be4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Some touch-ups in the JS code. Started adding Rhino-based tests for integration/unit-testing CGI/server modes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | json
Files: files | file ages | folders
SHA1:42a07be4c5460a1f461e42522aa07be217218be3
User & Date: stephan 2011-09-30 14:11:37
Context
2011-09-30
15:48
minor fix for fossil's internal handling of name=xyz parameter. check-in: 9f2535f1 user: stephan tags: json
14:11
Some touch-ups in the JS code. Started adding Rhino-based tests for integration/unit-testing CGI/server modes. check-in: 42a07be4 user: stephan tags: json
09:01
Merged in trunk [9bfa186be09f]. Fixed an inexplicable duplicate call to db_find_and_open_repository() which has since disappeared from the trunk. check-in: 8185bddf user: stephan tags: json
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added ajax/i-test/rhino-test.js.



















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
var TestApp = {
    serverUrl:'http://localhost:8080'
};
(function bootstrap() {
    var srcdir = '../js/';
    var includes = [srcdir+'json2.js',
                    srcdir+'whajaj.js',
                    srcdir+'fossil-ajaj.js'
                    ];
    for( var i in includes ) {
        load(includes[i]);
    }
    WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.rhino;
    TestApp.fossil = new FossilAjaj({
        asynchronous:false, /* rhino-based impl doesn't support asynch. */
        url:TestApp.serverUrl,
        beforeSend:function(req,opt){
            print("SENDING REQUEST: "+WhAjaj.stringify(opt));
        },
        afterSend:function(req,opt){
            print("SENT REQUEST: "+WhAjaj.stringify(opt));
        },
        onError:function(req,opt){
            print("ERROR: "+WhAjaj.stringify(opt));
        },
        onResponse:function(resp,req){
            print("GOT RESPONSE: "+(('string'===typeof resp) ? resp : WhAjaj.stringify(resp)));
        }
    });
})();

/**
    Throws an exception of cond is a falsy value.
*/
function assert(cond, descr){
    descr = descr || "Undescribed condition failed.";
    if(!cond){
        print("Assertion failed: "+descr);
        throw new Error(descr);
    }else{
        print("Assertion OK: "+descr);
    }
}

/**
    Calls func() in a try/catch block and throws an exception if
    func() does NOT throw.
*/
function assertThrows(func, descr){
    descr = descr || "Undescribed condition failed.";
    var ex;
    try{
        func();
    }catch(e){
        ex = e;
    }
    if(!ex){
        throw new Error("Function did not throw (as expected): "+descr);
    }else{
        print("Function threw (as expected): "+descr+": "+ex);
    }
}

/**
    Convenience form of TestApp.fossil.sendCommand(command,payload,ajajOpt).
*/
function send(command,payload, ajajOpt){
    TestApp.fossil.sendCommand(command,payload,ajajOpt);
}

/**
    Asserts that resp is-a Object, resp.fossil is-a string, and
    !resp.resultCode.
*/
function assertResponseOK(resp){
    assert('object' === typeof resp,'Response is-a object.');
    assert( 'string' === typeof resp.fossil, 'Response contains fossil property.');
    assert( !resp.resultCode, 'Response contains no error state.');
}

function testHAI(){
    TestApp.fossil.HAI({
        onResponse:function(resp,req){
            assertResponseOK(resp);
            TestApp.serverVersion = resp.fossil;
        }
    });
    assert( 'string' === typeof TestApp.serverVersion, 'server version = '+TestApp.serverVersion);
}
testHAI.description = 'Get server version info.';

function testWhoAmI_1(){
    TestApp.fossil.whoami('/json/whoami');
    assert('nobody' === TestApp.fossil.userName, 'User == nobody.' );
    assert('anonymous' !== TestApp.fossil.userName, 'User != anonymous.' );
    
}
testWhoAmI_1.description = 'First ever fossil-over-rhino test.';



(function runAllTests(){
    var testList = [
        testHAI,
        testWhoAmI_1
    ];
    var i, f;
    for( i = 0; i < testList.length; ++i ){
        f = testList[i];
        try{
            print("Running #"+(i+1)+": "+(f.description || "no description."));
            f();
        }catch(e){
            print("Test failed: "+e);
            throw e;
        }
    }

})();

print("Done!");

Changes to ajax/js/fossil-ajaj.js.

177
178
179
180
181
182
183















184











    to sendCommand().
*/
FossilAjaj.prototype.HAI = function(ajajOpt) {
    this.sendCommand('/json/HAI', null, ajajOpt);
};




































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    to sendCommand().
*/
FossilAjaj.prototype.HAI = function(ajajOpt) {
    this.sendCommand('/json/HAI', null, ajajOpt);
};


/**
    Sends a /json/whoami request. Updates this.userName and this.authToken
    based on the response, removing them if the response does not contain
    that data.
*/
FossilAjaj.prototype.whoami = function(ajajOpt) {
    var self = this;
    ajajOpt = this.ajaj.normalizeAjaxParameters( ajajOpt || {} );
    var oldOnResponse = ajajOpt.onResponse;
    ajajOpt.onResponse = function(resp,req) {
        var thisOpt = this;
        //alert('login response:\n'+WhAjaj.stringify(resp));
        if( resp && resp.payload ){
            if( resp.payload.authToken ) self.authToken = resp.payload.authToken;
            if( resp.payload.name ) self.userName = resp.payload.name;
        }
        else {
            delete self.userName;
            delete self.authToken
        }
        if( WhAjaj.isFunction(oldOnResponse) ) {
            try { oldOnResponse.apply(thisOpt,[resp,req]); }
            catch(e) {}
        }
    };
    self.sendCommand('/json/whoami', undefined, ajajOpt);
};

Changes to ajax/js/whajaj.js.

869
870
871
872
873
874
875
876




















































877
878
879
880
881
882
883
....
1027
1028
1029
1030
1031
1032
1033

1034
        }
        catch(e)
        {
            args.errorMessage = e.toString();
            WhAjaj.Connector.sendHelper.onSendError( request, args );
            return undefined;
        }
    }/*jQuery*/




















































};

/**
    An internal function which takes an object containing properties 
    for a WhAjaj.Connector network request. This function creates a new 
    object containing a superset of the properties from:

................................................................................
/**
    sendImpl() holds a concrete back-end connection implementation. It
    can be replaced with a custom implementation if one follows the rules
    described throughout this API. See WhAjaj.Connector.sendImpls for
    the concrete implementations included with this API.
*/
WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.XMLHttpRequest;

//WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.jQuery;







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>

869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
....
1079
1080
1081
1082
1083
1084
1085
1086
1087
        }
        catch(e)
        {
            args.errorMessage = e.toString();
            WhAjaj.Connector.sendHelper.onSendError( request, args );
            return undefined;
        }
    }/*jQuery*/,
    /**
        This is a concrete implementation of 
        WhAjaj.Connector.prototype.sendImpl() which uses the rhino 
        Java API to send requests and fetch the responses.

        Limitations vis-a-vis the interface:

        - timeouts are not supported.

        - asynchronous mode is not supported because implementing it
        requires the ability to kill a running thread (which is deprecated
        in the Java API).
    */
    rhino:function(request,args)
    {
        var data = request || undefined;
        if( data ) {
            if('string'!==typeof data) {
                try {
                    data = JSON.stringify(data);
                }
                catch(e) {
                    WhAjaj.Connector.sendHelper.onSendError( request, args );
                    return;
                }
            }
        }
        var url = new java.net.URL( args.url );
        var con;
        var IO = new JavaImporter(java.io);
        var wr;
        var rd, ln, json = [];
        try{
            con = url.openConnection();
            con.setDoOutput( true );
            wr = new IO.OutputStreamWriter(con.getOutputStream())
            wr.write(data);
            wr.flush();
            rd = new IO.BufferedReader(new IO.InputStreamReader(con.getInputStream()));
            while ((line = rd.readLine()) != null) {
                json.push(line);
            }

        }catch(e){
            args.errorMessage = e.toString();
            WhAjaj.Connector.sendHelper.onSendError( request, args );
            return undefined;
        }
        try { wr.close(); } catch(e) { /*ignore*/}
        try { rd.close(); } catch(e) { /*ignore*/}
        WhAjaj.Connector.sendHelper.onSendSuccess( request, json.join(''), args );
    }
};

/**
    An internal function which takes an object containing properties 
    for a WhAjaj.Connector network request. This function creates a new 
    object containing a superset of the properties from:

................................................................................
/**
    sendImpl() holds a concrete back-end connection implementation. It
    can be replaced with a custom implementation if one follows the rules
    described throughout this API. See WhAjaj.Connector.sendImpls for
    the concrete implementations included with this API.
*/
WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.XMLHttpRequest;
//WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.rhino;
//WhAjaj.Connector.prototype.sendImpl = WhAjaj.Connector.sendImpls.jQuery;