@@ -792,3 +792,112 @@ def test_browse(db_request):
792
792
"Programming Language :: Python" ,
793
793
],
794
794
)) == {(expected_release .name , expected_release .version )}
795
+
796
+
797
+ class TestMulticall :
798
+
799
+ def test_multicall (self , monkeypatch ):
800
+ dumped = pretend .stub (encode = lambda : None )
801
+ dumps = pretend .call_recorder (lambda * a , ** kw : dumped )
802
+ monkeypatch .setattr (xmlrpc .xmlrpc .client , 'dumps' , dumps )
803
+
804
+ loaded = pretend .stub ()
805
+ loads = pretend .call_recorder (lambda * a , ** kw : loaded )
806
+ monkeypatch .setattr (xmlrpc .xmlrpc .client , 'loads' , loads )
807
+
808
+ subreq = pretend .stub ()
809
+ blank = pretend .call_recorder (lambda * a , ** kw : subreq )
810
+ monkeypatch .setattr (xmlrpc .Request , 'blank' , blank )
811
+
812
+ body = pretend .stub ()
813
+ response = pretend .stub (body = body )
814
+
815
+ request = pretend .stub (
816
+ invoke_subrequest = pretend .call_recorder (lambda * a , ** kw : response ),
817
+ add_response_callback = pretend .call_recorder (
818
+ lambda * a , ** kw : response ),
819
+ )
820
+
821
+ callback = pretend .stub ()
822
+ monkeypatch .setattr (
823
+ xmlrpc ,
824
+ 'measure_response_content_length' ,
825
+ pretend .call_recorder (lambda metric_name : callback )
826
+ )
827
+
828
+ args = [
829
+ {'methodName' : 'search' , 'params' : [{'name' : 'foo' }]},
830
+ {'methodName' : 'browse' , 'params' : [{'classifiers' : ['bar' ]}]},
831
+ ]
832
+
833
+ responses = xmlrpc .multicall (request , args )
834
+
835
+ assert responses == [loaded , loaded ]
836
+ assert blank .calls == [
837
+ pretend .call ('/RPC2' , headers = {'Content-Type' : 'text/xml' }),
838
+ pretend .call ('/RPC2' , headers = {'Content-Type' : 'text/xml' }),
839
+ ]
840
+ assert request .invoke_subrequest .calls == [
841
+ pretend .call (subreq , use_tweens = True ),
842
+ pretend .call (subreq , use_tweens = True ),
843
+ ]
844
+ assert request .add_response_callback .calls == [
845
+ pretend .call (callback ),
846
+ ]
847
+ assert dumps .calls == [
848
+ pretend .call (({'name' : 'foo' },), methodname = 'search' ),
849
+ pretend .call (({'classifiers' : ['bar' ]},), methodname = 'browse' ),
850
+ ]
851
+ assert loads .calls == [pretend .call (body ), pretend .call (body )]
852
+
853
+ def test_recursive_multicall (self ):
854
+ request = pretend .stub ()
855
+ args = [
856
+ {'methodName' : 'system.multicall' , 'params' : []},
857
+ ]
858
+ with pytest .raises (xmlrpc .XMLRPCWrappedError ) as exc :
859
+ xmlrpc .multicall (request , args )
860
+
861
+ assert exc .value .faultString == (
862
+ 'ValueError: Cannot use system.multicall inside a multicall'
863
+ )
864
+
865
+ def test_missing_multicall_method (self ):
866
+ request = pretend .stub ()
867
+ args = [{}]
868
+ with pytest .raises (xmlrpc .XMLRPCWrappedError ) as exc :
869
+ xmlrpc .multicall (request , args )
870
+
871
+ assert exc .value .faultString == (
872
+ 'ValueError: Method name not provided'
873
+ )
874
+
875
+ def test_too_many_multicalls_method (self ):
876
+ request = pretend .stub ()
877
+ args = [{'methodName' : 'nah' }] * 21
878
+
879
+ with pytest .raises (xmlrpc .XMLRPCWrappedError ) as exc :
880
+ xmlrpc .multicall (request , args )
881
+
882
+ assert exc .value .faultString == (
883
+ 'ValueError: Multicall limit is 20 calls'
884
+ )
885
+
886
+ def test_measure_response_content_length (self ):
887
+ metric_name = 'some_metric_name'
888
+ callback = xmlrpc .measure_response_content_length (metric_name )
889
+
890
+ request = pretend .stub (
891
+ registry = pretend .stub (
892
+ datadog = pretend .stub (
893
+ histogram = pretend .call_recorder (lambda * a : None )
894
+ )
895
+ )
896
+ )
897
+ response = pretend .stub (content_length = pretend .stub ())
898
+
899
+ callback (request , response )
900
+
901
+ assert request .registry .datadog .histogram .calls == [
902
+ pretend .call (metric_name , response .content_length ),
903
+ ]
0 commit comments