File: 10-client.t

package info (click to toggle)
libtransmission-client-perl 0.0806-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 304 kB
  • sloc: perl: 3,004; makefile: 2
file content (269 lines) | stat: -rw-r--r-- 9,152 bytes parent folder | download | duplicates (3)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# ex:ts=4:sw=4:sts=4:et
use warnings;
use strict;
use lib qw(lib);
use Test::More;
use Transmission::Client;
use JSON::MaybeXS;

$SIG{'__DIE__'} = \&Carp::confess;

my($client, $rpc_response, $rpc_request, @torrents);
my $rpc_response_code = 409;

{
    no warnings 'redefine';
    *LWP::UserAgent::post = sub {
        my($lwp, $url, %args) = @_;
        my $res = HTTP::Response->new;
        $rpc_request = $args{'Content'};
        my($tag) = $rpc_request =~ /"tag":\s*(\d+)/;

        $rpc_response =~ s/"tag":\s*\w+/"tag":$tag/;
        $res->code($rpc_response_code);
        $res->content($rpc_response);
        $res->header('X-Transmission-Session-Id' => '1234567890') unless($client->session_id);
        $rpc_response_code = 200 if($rpc_response_code == 409);

        return $res;
    };

    Transmission::Session->meta->add_method(read_all => sub {});
}

{ # generic
    $client = Transmission::Client->new(autodie => 1);
    is($client->_autodie, 1, 'Transmission::Client will die on error');
    is($client->url, 'http://localhost:9091/transmission/rpc', 'default url is set');
    is($client->_url, $client->url, 'default _url is without username/password');
    isa_ok($client->_ua, 'LWP::UserAgent');

    $rpc_response = '{ "tag": TAG, "result": "success", "arguments": 123 }';
    is($client->session_id, '', 'session ID is not set until the first rpc() request');
    is($client->rpc('foo_bar'), 123, 'rpc() request responded with 123');
    request_has(method => 'foo-bar', 'foo_bar method was transformed to foo-bar');
    is($client->session_id, '1234567890', 'session ID was set by mocked HTTP request');

    $rpc_response = '{ "tag": TAG, "result": "success", "arguments": { "version": 42 } }';
    is($client->version, 42, 'got mocked Transmission version');
}

{ # add
    my %args = (
        download_dir => 'some/dir',
        paused => 1,
        peer_limit => 42,
    );

    eval { $client->add };
    like($@, qr{Need either filename or metainfo argument}, 'add() require filename or metainfo');
    eval { $client->add(filename => 'foo', metainfo => 'bar') };
    like($@, qr{Filename and metainfo argument crash}, 'add() cannot handle both filename and metainfo');

    $rpc_response = '{ "tag": TAG, "result": "success", "arguments": 1 }';
    ok($client->add(filename => 'foo.torrent'), 'add() torrent by filename');
    request_has(
        arguments => {
            filename => "foo.torrent",
        },
        method => "torrent-add",

        'add() with filename');

    ok($client->add(metainfo => {}), 'add() torrent with metainfo');
    request_has(
        arguments => {
            metainfo => undef,
        },
        method => "torrent-add",

        'add() with metainfo');
}

{ # remove, move, start, stop, verify / _do_ids_action()
    eval { $client->remove };
    like($@, qr{ids is required as argument}, 'remove() require ids argument');
    ok(!$client->has_torrents, 'remove() does not clear "torrents" attribute on failure');

    ok($client->remove(ids => 'all'), 'remove() with ids = "all"');
    ok($rpc_request !~ /ids/, 'remove() did not pass on ids, when ids = "all"');
    request_has(method => "torrent-remove", 'remove() does rpc method torrent-remove');

    ok($client->remove(ids => 42), 'remove() can take a single id');
    ok($client->remove(ids => [24, 42]), 'remove() can take a list of ids');
    like($rpc_request, qr{[24,\s*42]}, 'remove() with list of ids');
    ok(!$client->has_torrents, 'remove() also cleared "torrents" attribute');

    eval { $client->move };
    like($@, qr{location argument is required}, 'move() require "location"');

    ok($client->move(location => '/some/path', ids => 42), 'move() with location and ids');
    request_has(
        method => "torrent-set-location",
        arguments => {
            location => '/some/path',
            ids => [42],
        },

        'move() does rpc method torrent-set-location');

    ok($client->start(ids => 42), 'start() with location and ids');
    request_has(
        method => "torrent-start",
        arguments => {
            ids => [42],
        },

        'start() does rpc method torrent-start');

    ok($client->stop(ids => 42), 'stop() with location and ids');
    request_has(
        method => "torrent-stop",
        arguments => {
            ids => [42],
        },

        'stop() does rpc method torrent-stop');

    ok($client->verify(ids => 42), 'verify() with location and ids');
    request_has(
        method => "torrent-verify",
        arguments => {
            ids => [42],
        },

        'verify() does rpc method torrent-verify');
}

{
    $rpc_response = '{ "tag": TAG, "result": "success", "arguments": { "torrents":[] } }';
    is(my @torrents = $client->torrent_list, 0, 'torrent_list() contains zero objects');
    is_deeply($client->torrents, \@torrents, 'torrent_list() returns a list, while "torrents" contains an array-ref');

    $rpc_response = '{ "tag": TAG, "result": "success", "arguments": { "torrents":[] } }';

    $client->read_torrents;
    request_has(
        method => 'torrent-get',
        arguments => {
            fields => [qw(
                creator uploadRatio leechers sizeWhenDone recheckProgress
                maxConnectedPeers activityDate id swarmSpeed peersConnected
                pieceCount torrentFile name isPrivate webseedsSendingToUs
                timesCompleted addedDate downloadedEver downloaders peersKnown
                seeders downloadDir startDate desiredAvailable status
                peersSendingToUs peersGettingFromUs rateDownload corruptEver
                leftUntilDone uploadedEver error rateUpload manualAnnounceTime
                doneDate totalSize dateCreated pieceSize percentDone errorString
                haveValid hashString eta haveUnchecked comment uploadLimit
                downloadLimit seedRatioMode bandwidthPriority downloadLimited
                seedRatioLimit uploadLimited honorsSessionLimits)]
        },

        'read_torrents() with all fields',
    );

    $client->read_torrents(fields => [qw(name eta)]);
    request_has(
        method => 'torrent-get',
        arguments => {
            fields => [qw(id name eta)],
        },

        'read_torrents() with only specific fields',
    );

    $client->read_torrents(lazy_read => 1);
    request_has(
        method => 'torrent-get',
        arguments => {
            fields => ["id"],
        },

        'read_torrents() with lazy_read',
    );

    $client->read_torrents(ids => 42);
    request_has(
        method => 'torrent-get',
        arguments => {
            ids => [42],
        },

        'read_torrents() with ids',
    );
}

{ # RT#67691
    $client->rpc(foo_bar => ids => [1,2,'foo']);
    like($rpc_request, qr{"ids":\[1,2,"foo"\]}, 'Fix RT#67691: id "foo" is still a string');
}

TODO: {
    local $TODO = 'require better testing';
    ok(!$client->has_session, 'client has no session');
    ok($client->read_all, 'read_all() information');
    ok($client->has_session, 'read_all() set session attribute');
}

sub request_has {
    my $description = pop;
    my %args = @_;
    my @failed;

    note $description;

    # $rpc_request is set to the latest post request the test would have done
    my $rpc_req = decode_json($rpc_request);

    # All requests must have a method parameter
    ok exists $rpc_req->{method}, 'Existance of methods key';

    for my $top (keys %args) {
        if (ref $args{$top}) {
            for my $key (keys %{$args{$top}}) {
                if (not defined $args{$top}->{$key}) {
                    ok exists $rpc_req->{$top}->{$key},
                        "Existance of $top\->{$key}";
                    next;
                }

                if (not ref $rpc_req->{$top}->{$key} and
                    not ref $args{$top}->{$key}) {
                    is $rpc_req->{$top}->{$key}, $args{$top}->{$key},
                        "Comparing value for $top\->{$key}";
                    next;
                }

                is ref $rpc_req->{$top}->{$key}, 'ARRAY',
                    "$top\->{$key} should be an array";

                SKIP: {
                    skip "See previous test failure",
                        @{$args{$top}->{$key}} + 1 unless
                        ref $rpc_req->{$top}->{$key} eq 'ARRAY';

                    # Make sure all expected values exist
                    my %seen;
                    for my $elm (@{$args{$top}->{$key}}) {
                        ok(
                            grep({$elm eq $_} @{$rpc_req->{$top}->{$key}}),
                            "$top\->{$key} should have expected values ($elm)");
                        $seen{$elm} = 1;
                    }

                    # Make sure no unexpected values exist
                    is_deeply [
                        grep {! exists $seen{$_}} @{$rpc_req->{$top}->{$key}},
                    ], [], "No unexpected elements found in $top\->{$key}";

                }
            }
        }
        else {
            is $rpc_req->{$top}, $args{$top}, "Comparing value for $top";
        }
   }
}

done_testing();