Skip to content

Commit 32dc139

Browse files
authored
Add constness to input value generation (#811)
* Add constness to input value generation. As per the spec: https://spec.graphql.org/October2021/#Value Values should not be variables in a const context. The TLDR of this is that within schema definitions variables should bot be used on arguments. Within operations variables can should be used. Fixes #810
1 parent 3a26619 commit 32dc139

File tree

3 files changed

+24
-12
lines changed

3 files changed

+24
-12
lines changed

crates/apollo-smith/src/argument.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::input_value::Constness;
12
use crate::{
23
input_value::{InputValue, InputValueDef},
34
name::Name,
@@ -76,10 +77,10 @@ impl TryFrom<apollo_parser::cst::Argument> for Argument {
7677

7778
impl<'a> DocumentBuilder<'a> {
7879
/// Create an arbitrary vector of `Argument`
79-
pub fn arguments(&mut self) -> ArbitraryResult<Vec<Argument>> {
80+
pub fn arguments(&mut self, constness: Constness) -> ArbitraryResult<Vec<Argument>> {
8081
let num_arguments = self.u.int_in_range(0..=4)?;
8182
let arguments = (0..num_arguments)
82-
.map(|_| self.argument())
83+
.map(|_| self.argument(constness))
8384
.collect::<ArbitraryResult<Vec<_>>>()?;
8485

8586
Ok(arguments)
@@ -100,9 +101,9 @@ impl<'a> DocumentBuilder<'a> {
100101
}
101102

102103
/// Create an arbitrary `Argument`
103-
pub fn argument(&mut self) -> ArbitraryResult<Argument> {
104+
pub fn argument(&mut self, constness: Constness) -> ArbitraryResult<Argument> {
104105
let name = self.name()?;
105-
let value = self.input_value()?;
106+
let value = self.input_value(constness)?;
106107

107108
Ok(Argument { name, value })
108109
}

crates/apollo-smith/src/input_value.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ use apollo_compiler::Node;
1010
use arbitrary::Result as ArbitraryResult;
1111
use indexmap::IndexMap;
1212

13+
#[derive(Debug, Clone, Copy)]
14+
pub enum Constness {
15+
Const,
16+
NonConst,
17+
}
18+
1319
#[derive(Debug, Clone, PartialEq)]
1420
pub enum InputValue {
1521
Variable(Name),
@@ -160,8 +166,12 @@ impl TryFrom<apollo_parser::cst::InputValueDefinition> for InputValueDef {
160166

161167
impl<'a> DocumentBuilder<'a> {
162168
/// Create an arbitrary `InputValue`
163-
pub fn input_value(&mut self) -> ArbitraryResult<InputValue> {
164-
let val = match self.u.int_in_range(0..=8usize)? {
169+
pub fn input_value(&mut self, constness: Constness) -> ArbitraryResult<InputValue> {
170+
let index = match constness {
171+
Constness::Const => self.u.int_in_range(0..=7usize)?,
172+
Constness::NonConst => self.u.int_in_range(0..=8usize)?,
173+
};
174+
let val = match index {
165175
// Int
166176
0 => InputValue::Int(self.u.arbitrary()?),
167177
// Float
@@ -179,22 +189,22 @@ impl<'a> DocumentBuilder<'a> {
179189
let enum_choosed = self.choose_enum()?.clone();
180190
InputValue::Enum(self.arbitrary_variant(&enum_choosed)?.clone())
181191
} else {
182-
self.input_value()?
192+
self.input_value(constness)?
183193
}
184194
}
185195
// List
186196
6 => {
187197
// FIXME: it's semantically wrong it should always be the same type inside
188198
InputValue::List(
189199
(0..self.u.int_in_range(2..=4usize)?)
190-
.map(|_| self.input_value())
200+
.map(|_| self.input_value(constness))
191201
.collect::<ArbitraryResult<Vec<_>>>()?,
192202
)
193203
}
194204
// Object
195205
7 => InputValue::Object(
196206
(0..self.u.int_in_range(2..=4usize)?)
197-
.map(|_| Ok((self.name()?, self.input_value()?)))
207+
.map(|_| Ok((self.name()?, self.input_value(constness)?)))
198208
.collect::<ArbitraryResult<Vec<_>>>()?,
199209
),
200210
// Variable TODO: only generate valid variable name (existing variables)
@@ -287,7 +297,7 @@ impl<'a> DocumentBuilder<'a> {
287297
.u
288298
.arbitrary()
289299
.unwrap_or(false)
290-
.then(|| self.input_value())
300+
.then(|| self.input_value(Constness::Const))
291301
.transpose()?;
292302

293303
input_values.push(InputValueDef {
@@ -318,7 +328,7 @@ impl<'a> DocumentBuilder<'a> {
318328
.u
319329
.arbitrary()
320330
.unwrap_or(false)
321-
.then(|| self.input_value())
331+
.then(|| self.input_value(Constness::Const))
322332
.transpose()?;
323333

324334
Ok(InputValueDef {

crates/apollo-smith/src/variable.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::input_value::Constness;
12
use crate::{
23
directive::{Directive, DirectiveLocation},
34
input_value::InputValue,
@@ -51,7 +52,7 @@ impl<'a> DocumentBuilder<'a> {
5152
.u
5253
.arbitrary()
5354
.unwrap_or(false)
54-
.then(|| self.input_value())
55+
.then(|| self.input_value(Constness::Const))
5556
.transpose()?;
5657
let directives = self.directives(DirectiveLocation::VariableDefinition)?;
5758

0 commit comments

Comments
 (0)