11using System ;
2+ using System . Collections . Generic ;
23using System . Linq ;
34using FluentAssertions ;
45using Nest ;
@@ -18,8 +19,8 @@ public void DescriptorsHaveToBeMarkedWithIDescriptor()
1819 var notDescriptors = new [ ] { typeof ( ClusterProcessOpenFileDescriptors ) . Name , "DescriptorForAttribute" } ;
1920
2021 var descriptors = from t in typeof ( DescriptorBase < , > ) . Assembly ( ) . Types ( )
21- where t . IsClass ( )
22- && t . Name . Contains ( "Descriptor" )
22+ where t . IsClass ( )
23+ && t . Name . Contains ( "Descriptor" )
2324 && ! notDescriptors . Contains ( t . Name )
2425 && ! t . GetInterfaces ( ) . Any ( i => i == typeof ( IDescriptor ) )
2526 select t . FullName ;
@@ -65,9 +66,80 @@ where lastArgIsNotInterface
6566 selectorMethods . Should ( ) . BeEmpty ( ) ;
6667 }
6768
69+ /**
70+ * Descriptor methods that assign to a nullable bool property should accept
71+ * a nullable bool with a default value
72+ */
73+ [ U ]
74+ public void DescriptorMethodsAcceptNullableBoolsForQueriesWithNullableBoolProperties ( )
75+ {
76+ var queries =
77+ from t in typeof ( IQuery ) . Assembly ( ) . Types ( )
78+ where t . IsInterface ( ) && typeof ( IQuery ) . IsAssignableFrom ( t )
79+ where t . GetProperties ( ) . Any ( p => p . PropertyType == typeof ( bool ? ) )
80+ select t ;
81+
82+ var descriptors =
83+ from t in typeof ( DescriptorBase < , > ) . Assembly ( ) . Types ( )
84+ where t . IsClass ( ) && typeof ( IDescriptor ) . IsAssignableFrom ( t )
85+ where t . GetInterfaces ( ) . Intersect ( queries ) . Any ( )
86+ select t ;
87+
88+ var breakingDescriptors = new List < string > ( ) ;
89+
90+ // exceptions
91+ var parameterlessMethods = new List < MethodInfo >
92+ {
93+ typeof ( BoolQueryDescriptor < > ) . GetMethod ( nameof ( BoolQueryDescriptor < object > . DisableCoord ) )
94+ } ;
95+
96+ var nonDefaultValueMethods = new List < MethodInfo >
97+ {
98+ typeof ( SpanNearQueryDescriptor < > ) . GetMethod ( nameof ( SpanNearQueryDescriptor < object > . CollectPayloads ) ) ,
99+ typeof ( SpanNearQueryDescriptor < > ) . GetMethod ( nameof ( SpanNearQueryDescriptor < object > . InOrder ) ) ,
100+ } ;
101+
102+ foreach ( var query in queries )
103+ {
104+ var descriptor = descriptors . First ( d => query . IsAssignableFrom ( d ) ) ;
105+ foreach ( var boolProperty in query . GetProperties ( ) . Where ( p => p . PropertyType == typeof ( bool ? ) ) )
106+ {
107+ var descriptorMethod = descriptor . GetMethod ( boolProperty . Name ) ;
108+ if ( descriptorMethod == null )
109+ throw new Exception ( $ "No method for property { boolProperty . Name } on { descriptor . Name } ") ;
110+
111+ var parameters = descriptorMethod . GetParameters ( ) ;
112+
113+ if ( ! parameters . Any ( ) )
114+ {
115+ if ( parameterlessMethods . Contains ( descriptorMethod ) )
116+ continue ;
117+
118+ throw new Exception ( $ "No parameter for method { descriptorMethod . Name } on { descriptor . Name } ") ;
119+ }
120+
121+ if ( parameters . Length > 1 )
122+ throw new Exception ( $ "More than one parameter for method { descriptorMethod . Name } on { descriptor . Name } ") ;
123+
124+ if ( parameters [ 0 ] . ParameterType != typeof ( bool ? ) )
125+ breakingDescriptors . Add ( $ "{ descriptor . FullName } method { descriptorMethod . Name } does not take nullable bool") ;
126+
127+ if ( ! parameters [ 0 ] . HasDefaultValue )
128+ {
129+ if ( nonDefaultValueMethods . Contains ( descriptorMethod ) )
130+ continue ;
131+
132+ breakingDescriptors . Add ( $ "{ descriptor . FullName } method { descriptorMethod . Name } does not have a default value") ;
133+ }
134+ }
135+ }
136+
137+ breakingDescriptors . Should ( ) . BeEmpty ( ) ;
138+ }
139+
68140 //TODO methods taking params should also have a version taking IEnumerable
69141
70- //TODO methods named Index or Indices that
142+ //TODO methods named Index or Indices that
71143
72144 //TODO some interfaces are implemented by both requests as well isolated classes to be used elsewhere in the DSL
73145 //We need to write tests that these have the same public methods so we do not accidentally add it without adding it to the interface
0 commit comments