microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/compiler/qsc_doc_gen/src/generate_docs/tests.rs
324lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use crate::generate_docs::{generate_docs, generate_summaries_map, metadata_to_markdown}; |
| 5 | use expect_test::expect; |
| 6 | use std::collections::BTreeMap; |
| 7 | |
| 8 | /// Testing helper function that returns summaries as a structured map |
| 9 | /// for easier test validation. Returns a map where each namespace maps to |
| 10 | /// a vector of markdown strings, one per item. |
| 11 | pub fn generate_summaries_for_testing() -> BTreeMap<String, Vec<String>> { |
| 12 | let summaries_map = generate_summaries_map(); |
| 13 | |
| 14 | let mut result = BTreeMap::new(); |
| 15 | |
| 16 | for (ns, items) in summaries_map { |
| 17 | let mut item_markdowns = Vec::new(); |
| 18 | |
| 19 | for item in items { |
| 20 | let markdown = metadata_to_markdown(&item); |
| 21 | item_markdowns.push(markdown); |
| 22 | } |
| 23 | |
| 24 | result.insert(ns, item_markdowns); |
| 25 | } |
| 26 | |
| 27 | result |
| 28 | } |
| 29 | |
| 30 | #[test] |
| 31 | fn generates_standard_item() { |
| 32 | let files = generate_docs(None, None, None); |
| 33 | let (_, metadata, contents) = files |
| 34 | .iter() |
| 35 | .find(|(file_name, _, _)| &**file_name == "Std.Core/Length.md") |
| 36 | .expect("Could not find doc file for Length"); |
| 37 | let full_contents = format!("{metadata}\n\n{contents}"); |
| 38 | |
| 39 | expect![[r#" |
| 40 | --- |
| 41 | uid: Qdk.Std.Core.Length |
| 42 | title: Length function |
| 43 | description: "Q# Length function: Returns the number of elements in the input array `a`." |
| 44 | ms.date: {TIMESTAMP} |
| 45 | qsharp.kind: function |
| 46 | qsharp.package: __Core__ |
| 47 | qsharp.namespace: Std.Core |
| 48 | qsharp.name: Length |
| 49 | qsharp.summary: "Returns the number of elements in the input array `a`." |
| 50 | --- |
| 51 | |
| 52 | # Length function |
| 53 | |
| 54 | Fully qualified name: Std.Core.Length |
| 55 | |
| 56 | ```qsharp |
| 57 | function Length<'T>(a : 'T[]) : Int |
| 58 | ``` |
| 59 | |
| 60 | ## Summary |
| 61 | Returns the number of elements in the input array `a`. |
| 62 | |
| 63 | ## Input |
| 64 | ### a |
| 65 | Input array. |
| 66 | |
| 67 | ## Output |
| 68 | The total number of elements in the input array `a`. |
| 69 | |
| 70 | ## Example |
| 71 | ```qsharp |
| 72 | Message($"{ Length([0, 0, 0]) }"); // Prints 3 |
| 73 | ``` |
| 74 | "#]] |
| 75 | .assert_eq(full_contents.as_str()); |
| 76 | } |
| 77 | |
| 78 | #[test] |
| 79 | fn generates_unrestricted_item() { |
| 80 | let files = generate_docs(None, None, None); |
| 81 | let (_, metadata, contents) = files |
| 82 | .iter() |
| 83 | .find(|(file_name, _, _)| &**file_name == "Std.Diagnostics/CheckZero.md") |
| 84 | .expect("Could not file doc file for CheckZero"); |
| 85 | let full_contents = format!("{metadata}\n\n{contents}"); |
| 86 | |
| 87 | expect![[r#" |
| 88 | --- |
| 89 | uid: Qdk.Std.Diagnostics.CheckZero |
| 90 | title: CheckZero operation |
| 91 | description: "Q# CheckZero operation: Checks whether a qubit is in the |0⟩ state, returning true if it is." |
| 92 | ms.date: {TIMESTAMP} |
| 93 | qsharp.kind: operation |
| 94 | qsharp.package: __Std__ |
| 95 | qsharp.namespace: Std.Diagnostics |
| 96 | qsharp.name: CheckZero |
| 97 | qsharp.summary: "Checks whether a qubit is in the |0⟩ state, returning true if it is." |
| 98 | --- |
| 99 | |
| 100 | # CheckZero operation |
| 101 | |
| 102 | Fully qualified name: Std.Diagnostics.CheckZero |
| 103 | |
| 104 | ```qsharp |
| 105 | operation CheckZero(qubit : Qubit) : Bool |
| 106 | ``` |
| 107 | |
| 108 | ## Summary |
| 109 | Checks whether a qubit is in the |0⟩ state, returning true if it is. |
| 110 | |
| 111 | ## Description |
| 112 | This operation checks whether a qubit is in the |0⟩ state. It will return true only |
| 113 | if the qubit is deterministically in the |0⟩ state, and will return false otherwise. This operation |
| 114 | does not change the state of the qubit. |
| 115 | |
| 116 | ## Input |
| 117 | ### qubit |
| 118 | The qubit to check. |
| 119 | ## Output |
| 120 | True if the qubit is in the |0⟩ state, false otherwise. |
| 121 | |
| 122 | ## Remarks |
| 123 | This operation is useful for checking whether a qubit is in the |0⟩ state during simulation. It is not possible to check |
| 124 | this on hardware without measuring the qubit, which could change the state. |
| 125 | "#]] |
| 126 | .assert_eq(full_contents.as_str()); |
| 127 | } |
| 128 | |
| 129 | #[test] |
| 130 | fn redirect_generation() { |
| 131 | let files = generate_docs(None, None, None); |
| 132 | let (_, metadata, contents) = files |
| 133 | .iter() |
| 134 | .find(|(file_name, _, _)| &**file_name == "Microsoft.Quantum.Core/Length.md") |
| 135 | .expect("Could not find doc file for Length"); |
| 136 | let full_contents = format!("{metadata}\n\n{contents}"); |
| 137 | |
| 138 | expect" |
| 143 | ms.date: {TIMESTAMP} |
| 144 | qsharp.kind: export |
| 145 | qsharp.package: __Std__ |
| 146 | qsharp.namespace: Microsoft.Quantum.Core |
| 147 | qsharp.name: Length |
| 148 | qsharp.summary: "This is an exported item. The actual definition is found here: [Std.Core.Length](xref:Qdk.Std.Core.Length)" |
| 149 | --- |
| 150 | |
| 151 | # Length exported item |
| 152 | |
| 153 | Fully qualified name: Microsoft.Quantum.Core.Length |
| 154 | |
| 155 | This is an exported item. The actual definition is found here: [Std.Core.Length](xref:Qdk.Std.Core.Length) |
| 156 | "#]] |
| 157 | .assert_eq(full_contents.as_str()); |
| 158 | } |
| 159 | |
| 160 | #[test] |
| 161 | fn index_file_generation() { |
| 162 | let files = generate_docs(None, None, None); |
| 163 | let (_, metadata, contents) = files |
| 164 | .iter() |
| 165 | .find(|(file_name, _, _)| &**file_name == "Std.Core/index.md") |
| 166 | .expect("Could not find Std.Core Table of Contents file"); |
| 167 | let full_contents = format!("{metadata}\n\n{contents}"); |
| 168 | |
| 169 | expect | Represents a complex number by its real and imaginary components. The real component can be accessed via the `Real` field, and the imaginary component via the `Imag` field. Complex literals can be written using the form `a + bi`, where `a` is the Double literal for the real part and `b` is the Double literal for the imaginary part. | |
| 185 | | [Length](xref:Qdk.Std.Core.Length) | Returns the number of elements in the input array `a`. | |
| 186 | | [Repeated](xref:Qdk.Std.Core.Repeated) | Creates an array of given `length` with all elements equal to given `value`. `length` must be a non-negative integer. | |
| 187 | "#]] |
| 188 | .assert_eq(full_contents.as_str()); |
| 189 | } |
| 190 | |
| 191 | #[test] |
| 192 | fn top_index_file_generation() { |
| 193 | let files = generate_docs(None, None, None); |
| 194 | let (_, metadata, contents) = files |
| 195 | .iter() |
| 196 | .find(|(file_name, _, _)| &**file_name == "index.md") |
| 197 | .expect("Could not find top-level Table of Contents file"); |
| 198 | let full_contents = format!("{metadata}\n\n{contents}"); |
| 199 | |
| 200 | expect | Re-exported functions. | |
| 216 | | [`Std.Arithmetic`](xref:Qdk.Std.Arithmetic-toc) | Items for working with quantum arithmetic operations. | |
| 217 | | [`Std.Arrays`](xref:Qdk.Std.Arrays-toc) | Items for working with arrays. | |
| 218 | | [`Std.Canon`](xref:Qdk.Std.Canon-toc) | Canonical implementations of common classical and quantum utilities. | |
| 219 | | [`Std.Convert`](xref:Qdk.Std.Convert-toc) | Items for converting between different types. | |
| 220 | | [`Std.Core`](xref:Qdk.Std.Core-toc) | Items for language built-in operations. | |
| 221 | | [`Std.Diagnostics`](xref:Qdk.Std.Diagnostics-toc) | Items for debugging and testing quantum programs. | |
| 222 | | [`Std.Intrinsic`](xref:Qdk.Std.Intrinsic-toc) | Items that provide core quantum operations. | |
| 223 | | [`Std.Logical`](xref:Qdk.Std.Logical-toc) | Boolean Logic functions. | |
| 224 | | [`Std.Math`](xref:Qdk.Std.Math-toc) | Items for classical math operations. | |
| 225 | | [`Std.Measurement`](xref:Qdk.Std.Measurement-toc) | Items for measuring quantum results. | |
| 226 | | [`Std.Random`](xref:Qdk.Std.Random-toc) | Items for creating random values. | |
| 227 | | [`Std.Range`](xref:Qdk.Std.Range-toc) | Items for working with ranges. | |
| 228 | | [`Std.ResourceEstimation`](xref:Qdk.Std.ResourceEstimation-toc) | Items for working with the Azure Quantum Resource Estimator. | |
| 229 | | [`Std.StatePreparation`](xref:Qdk.Std.StatePreparation-toc) | Items for preparing a quantum state. | |
| 230 | | [`Std.TableLookup`](xref:Qdk.Std.TableLookup-toc) | Items for performing quantum table lookups. | |
| 231 | "#]] |
| 232 | .assert_eq(full_contents.as_str()); |
| 233 | } |
| 234 | |
| 235 | #[test] |
| 236 | fn generates_standard_item_summary() { |
| 237 | let summaries = generate_summaries_for_testing(); |
| 238 | // Find a summary for a known item, e.g., Std.Core.Length |
| 239 | let core_summaries = summaries |
| 240 | .get("Std.Core") |
| 241 | .expect("Could not find Std.Core namespace"); |
| 242 | let length_summary = core_summaries |
| 243 | .iter() |
| 244 | .find(|item| item.contains("## Length")) |
| 245 | .expect("Could not find summary for Length"); |
| 246 | |
| 247 | expect![[r#" |
| 248 | ## Length |
| 249 | |
| 250 | ```qsharp |
| 251 | function Length<'T>(a : 'T[]) : Int |
| 252 | ``` |
| 253 | |
| 254 | Returns the number of elements in the input array `a`. |
| 255 | |
| 256 | "#]] |
| 257 | .assert_eq(length_summary); |
| 258 | } |
| 259 | |
| 260 | #[test] |
| 261 | fn generates_std_core_summary() { |
| 262 | let summaries = generate_summaries_for_testing(); |
| 263 | let core_summaries = summaries |
| 264 | .get("Std.Core") |
| 265 | .expect("Could not find Std.Core namespace"); |
| 266 | |
| 267 | // Combine all summaries for the namespace |
| 268 | let combined_summary = core_summaries.join("\n\n"); |
| 269 | |
| 270 | expect![[r#" |
| 271 | ## Complex |
| 272 | |
| 273 | ```qsharp |
| 274 | struct Complex { Real : Double, Imag : Double } |
| 275 | ``` |
| 276 | |
| 277 | Represents a complex number by its real and imaginary components. The real component can be accessed via the `Real` field, and the imaginary component via the `Imag` field. Complex literals can be written using the form `a + bi`, where `a` is the Double literal for the real part and `b` is the Double literal for the imaginary part. |
| 278 | |
| 279 | |
| 280 | |
| 281 | ## Length |
| 282 | |
| 283 | ```qsharp |
| 284 | function Length<'T>(a : 'T[]) : Int |
| 285 | ``` |
| 286 | |
| 287 | Returns the number of elements in the input array `a`. |
| 288 | |
| 289 | |
| 290 | |
| 291 | ## Repeated |
| 292 | |
| 293 | ```qsharp |
| 294 | function Repeated<'T>(value : 'T, length : Int) : 'T[] |
| 295 | ``` |
| 296 | |
| 297 | Creates an array of given `length` with all elements equal to given `value`. `length` must be a non-negative integer. |
| 298 | |
| 299 | "#]] |
| 300 | .assert_eq(&combined_summary); |
| 301 | } |
| 302 | |
| 303 | #[test] |
| 304 | fn generates_summary_for_reexport() { |
| 305 | let summaries = generate_summaries_for_testing(); |
| 306 | let length_summary = summaries |
| 307 | .get("Microsoft.Quantum.Core") |
| 308 | .expect("Could not find Microsoft.Quantum.Core namespace") |
| 309 | .iter() |
| 310 | .find(|item| item.contains("## Length")) |
| 311 | .expect("Could not find summary for Length"); |
| 312 | |
| 313 | expect |
| 321 | |
| 322 | "#]] |
| 323 | .assert_eq(length_summary); |
| 324 | } |
| 325 | |