1 //===-- ArchSpecTest.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gtest/gtest.h" 10 11 #include "lldb/Utility/ArchSpec.h" 12 #include "llvm/BinaryFormat/ELF.h" 13 #include "llvm/BinaryFormat/MachO.h" 14 15 using namespace lldb; 16 using namespace lldb_private; 17 18 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) { 19 20 // Success conditions. Valid cpu/subtype combinations using both - and . 21 ArchSpec AS; 22 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS)); 23 EXPECT_EQ(12u, AS.GetMachOCPUType()); 24 EXPECT_EQ(10u, AS.GetMachOCPUSubType()); 25 26 AS = ArchSpec(); 27 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS)); 28 EXPECT_EQ(12u, AS.GetMachOCPUType()); 29 EXPECT_EQ(15u, AS.GetMachOCPUSubType()); 30 31 AS = ArchSpec(); 32 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS)); 33 EXPECT_EQ(12u, AS.GetMachOCPUType()); 34 EXPECT_EQ(15u, AS.GetMachOCPUSubType()); 35 36 // Failure conditions. 37 38 // Valid string, unknown cpu/subtype. 39 AS = ArchSpec(); 40 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS)); 41 EXPECT_EQ(0u, AS.GetMachOCPUType()); 42 EXPECT_EQ(0u, AS.GetMachOCPUSubType()); 43 44 // Missing / invalid cpu or subtype 45 AS = ArchSpec(); 46 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS)); 47 48 AS = ArchSpec(); 49 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS)); 50 51 AS = ArchSpec(); 52 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS)); 53 54 // Empty string. 55 AS = ArchSpec(); 56 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS)); 57 } 58 59 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) { 60 ArchSpec AS; 61 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS)); 62 EXPECT_EQ(12u, AS.GetMachOCPUType()); 63 EXPECT_EQ(15u, AS.GetMachOCPUSubType()); 64 EXPECT_EQ("vendor", AS.GetTriple().getVendorName()); 65 EXPECT_EQ("os", AS.GetTriple().getOSName()); 66 67 AS = ArchSpec(); 68 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS)); 69 EXPECT_EQ(12u, AS.GetMachOCPUType()); 70 EXPECT_EQ(10u, AS.GetMachOCPUSubType()); 71 EXPECT_EQ("vendor", AS.GetTriple().getVendorName()); 72 EXPECT_EQ("os", AS.GetTriple().getOSName()); 73 74 AS = ArchSpec(); 75 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS)); 76 EXPECT_EQ(12u, AS.GetMachOCPUType()); 77 EXPECT_EQ(15u, AS.GetMachOCPUSubType()); 78 EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName()); 79 EXPECT_EQ("name", AS.GetTriple().getOSName()); 80 81 // These there should parse correctly, but the vendor / OS should be defaulted 82 // since they are unrecognized. 83 AS = ArchSpec(); 84 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS)); 85 EXPECT_EQ(12u, AS.GetMachOCPUType()); 86 EXPECT_EQ(10u, AS.GetMachOCPUSubType()); 87 EXPECT_EQ("apple", AS.GetTriple().getVendorName()); 88 EXPECT_EQ("", AS.GetTriple().getOSName()); 89 90 AS = ArchSpec(); 91 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS)); 92 93 AS = ArchSpec(); 94 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS)); 95 } 96 97 TEST(ArchSpecTest, TestSetTriple) { 98 ArchSpec AS; 99 100 // Various flavors of valid triples. 101 EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin")); 102 EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType()); 103 EXPECT_EQ(10u, AS.GetMachOCPUSubType()); 104 EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str()) 105 .consume_front("armv7f-apple-darwin")); 106 EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore()); 107 108 AS = ArchSpec(); 109 EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin")); 110 EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType()); 111 EXPECT_EQ(100u, AS.GetMachOCPUSubType()); 112 EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str()) 113 .consume_front("powerpc-apple-darwin")); 114 EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore()); 115 116 AS = ArchSpec(); 117 EXPECT_TRUE(AS.SetTriple("i686-pc-windows")); 118 EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch()); 119 EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor()); 120 EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS()); 121 EXPECT_TRUE( 122 llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows")); 123 EXPECT_STREQ("i686", AS.GetArchitectureName()); 124 EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore()); 125 126 AS = ArchSpec(); 127 EXPECT_TRUE(AS.SetTriple("msp430---elf")); 128 EXPECT_EQ(llvm::Triple::msp430, AS.GetTriple().getArch()); 129 EXPECT_STREQ("msp430", AS.GetArchitectureName()); 130 EXPECT_EQ(ArchSpec::eCore_msp430, AS.GetCore()); 131 132 AS = ArchSpec(); 133 EXPECT_TRUE(AS.SetTriple("amd64-unknown-openbsd")); 134 EXPECT_EQ(llvm::Triple::x86_64, AS.GetTriple().getArch()); 135 EXPECT_STREQ("amd64", AS.GetArchitectureName()); 136 EXPECT_EQ(ArchSpec::eCore_x86_64_amd64, AS.GetCore()); 137 138 // Various flavors of invalid triples. 139 AS = ArchSpec(); 140 EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown")); 141 142 AS = ArchSpec(); 143 EXPECT_FALSE(AS.SetTriple("unknown")); 144 145 AS = ArchSpec(); 146 EXPECT_FALSE(AS.SetTriple("")); 147 } 148 149 TEST(ArchSpecTest, MergeFrom) { 150 { 151 ArchSpec A; 152 ArchSpec B("x86_64-pc-linux"); 153 154 EXPECT_FALSE(A.IsValid()); 155 ASSERT_TRUE(B.IsValid()); 156 EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch()); 157 EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor()); 158 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 159 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore()); 160 161 A.MergeFrom(B); 162 ASSERT_TRUE(A.IsValid()); 163 EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch()); 164 EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor()); 165 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 166 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore()); 167 } 168 { 169 ArchSpec A("aarch64"); 170 ArchSpec B("aarch64--linux-android"); 171 172 ArchSpec C("arm64_32"); 173 ArchSpec D("arm64_32--watchos"); 174 175 EXPECT_TRUE(A.IsValid()); 176 EXPECT_TRUE(B.IsValid()); 177 EXPECT_TRUE(C.IsValid()); 178 EXPECT_TRUE(D.IsValid()); 179 180 EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch()); 181 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 182 B.GetTriple().getVendor()); 183 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 184 EXPECT_EQ(llvm::Triple::EnvironmentType::Android, 185 B.GetTriple().getEnvironment()); 186 187 A.MergeFrom(B); 188 EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch()); 189 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 190 A.GetTriple().getVendor()); 191 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 192 EXPECT_EQ(llvm::Triple::EnvironmentType::Android, 193 A.GetTriple().getEnvironment()); 194 195 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, D.GetTriple().getArch()); 196 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 197 D.GetTriple().getVendor()); 198 EXPECT_EQ(llvm::Triple::OSType::WatchOS, D.GetTriple().getOS()); 199 200 C.MergeFrom(D); 201 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, C.GetTriple().getArch()); 202 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 203 C.GetTriple().getVendor()); 204 EXPECT_EQ(llvm::Triple::OSType::WatchOS, C.GetTriple().getOS()); 205 } 206 { 207 ArchSpec A, B; 208 A.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM, 209 LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_NONE); 210 B.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM, 211 LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_LINUX); 212 213 EXPECT_TRUE(A.IsValid()); 214 EXPECT_TRUE(B.IsValid()); 215 216 EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch()); 217 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 218 B.GetTriple().getVendor()); 219 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 220 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment, 221 B.GetTriple().getEnvironment()); 222 223 A.MergeFrom(B); 224 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch()); 225 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 226 A.GetTriple().getVendor()); 227 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 228 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment, 229 A.GetTriple().getEnvironment()); 230 } 231 { 232 ArchSpec A("arm--linux-eabihf"); 233 ArchSpec B("armv8l--linux-gnueabihf"); 234 235 EXPECT_TRUE(A.IsValid()); 236 EXPECT_TRUE(B.IsValid()); 237 238 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch()); 239 EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch()); 240 241 EXPECT_EQ(ArchSpec::eCore_arm_generic, A.GetCore()); 242 EXPECT_EQ(ArchSpec::eCore_arm_armv8l, B.GetCore()); 243 244 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 245 A.GetTriple().getVendor()); 246 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 247 B.GetTriple().getVendor()); 248 249 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 250 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 251 252 EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF, 253 A.GetTriple().getEnvironment()); 254 EXPECT_EQ(llvm::Triple::EnvironmentType::GNUEABIHF, 255 B.GetTriple().getEnvironment()); 256 257 A.MergeFrom(B); 258 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch()); 259 EXPECT_EQ(ArchSpec::eCore_arm_armv8l, A.GetCore()); 260 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 261 A.GetTriple().getVendor()); 262 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 263 EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF, 264 A.GetTriple().getEnvironment()); 265 } 266 } 267 268 TEST(ArchSpecTest, MergeFromMachOUnknown) { 269 class MyArchSpec : public ArchSpec { 270 public: 271 MyArchSpec() { 272 this->SetTriple("unknown-mach-64"); 273 this->m_core = ArchSpec::eCore_uknownMach64; 274 this->m_byte_order = eByteOrderLittle; 275 this->m_flags = 0; 276 } 277 }; 278 279 MyArchSpec A; 280 ASSERT_TRUE(A.IsValid()); 281 MyArchSpec B; 282 ASSERT_TRUE(B.IsValid()); 283 A.MergeFrom(B); 284 ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64); 285 } 286 287 TEST(ArchSpecTest, Compatibility) { 288 { 289 ArchSpec A("x86_64-apple-macosx10.12"); 290 ArchSpec B("x86_64-apple-macosx10.12"); 291 ASSERT_TRUE(A.IsExactMatch(B)); 292 ASSERT_TRUE(A.IsCompatibleMatch(B)); 293 } 294 { 295 // The version information is auxiliary to support availability but 296 // doesn't affect compatibility. 297 ArchSpec A("x86_64-apple-macosx10.11"); 298 ArchSpec B("x86_64-apple-macosx10.12"); 299 ASSERT_TRUE(A.IsExactMatch(B)); 300 ASSERT_TRUE(A.IsCompatibleMatch(B)); 301 } 302 { 303 ArchSpec A("x86_64-apple-macosx10.13"); 304 ArchSpec B("x86_64h-apple-macosx10.13"); 305 ASSERT_FALSE(A.IsExactMatch(B)); 306 ASSERT_TRUE(A.IsCompatibleMatch(B)); 307 } 308 { 309 ArchSpec A("x86_64-apple-macosx"); 310 ArchSpec B("x86_64-apple-ios-simulator"); 311 ASSERT_FALSE(A.IsExactMatch(B)); 312 ASSERT_FALSE(A.IsCompatibleMatch(B)); 313 } 314 { 315 ArchSpec A("x86_64-*-*"); 316 ArchSpec B("x86_64-apple-ios-simulator"); 317 ASSERT_FALSE(A.IsExactMatch(B)); 318 ASSERT_FALSE(A.IsCompatibleMatch(B)); 319 ASSERT_FALSE(B.IsExactMatch(A)); 320 ASSERT_FALSE(B.IsCompatibleMatch(A)); 321 } 322 { 323 ArchSpec A("x86_64-apple-ios"); 324 ArchSpec B("x86_64-apple-ios-simulator"); 325 ASSERT_FALSE(A.IsExactMatch(B)); 326 ASSERT_FALSE(A.IsCompatibleMatch(B)); 327 ASSERT_FALSE(B.IsExactMatch(A)); 328 ASSERT_FALSE(B.IsCompatibleMatch(A)); 329 } 330 { 331 // FIXME: This is surprisingly not equivalent to "x86_64-*-*". 332 ArchSpec A("x86_64"); 333 ArchSpec B("x86_64-apple-ios-simulator"); 334 ASSERT_FALSE(A.IsExactMatch(B)); 335 ASSERT_TRUE(A.IsCompatibleMatch(B)); 336 ASSERT_FALSE(B.IsExactMatch(A)); 337 ASSERT_TRUE(B.IsCompatibleMatch(A)); 338 } 339 { 340 ArchSpec A("arm64-apple-ios"); 341 ArchSpec B("arm64-apple-ios-simulator"); 342 ASSERT_FALSE(A.IsExactMatch(B)); 343 ASSERT_FALSE(A.IsCompatibleMatch(B)); 344 ASSERT_FALSE(B.IsCompatibleMatch(A)); 345 ASSERT_FALSE(B.IsCompatibleMatch(A)); 346 } 347 { 348 ArchSpec A("arm64-*-*"); 349 ArchSpec B("arm64-apple-ios"); 350 ASSERT_FALSE(A.IsExactMatch(B)); 351 // FIXME: This looks unintuitive and we should investigate whether 352 // this is the desired behavior. 353 ASSERT_FALSE(A.IsCompatibleMatch(B)); 354 } 355 { 356 ArchSpec A("x86_64-*-*"); 357 ArchSpec B("x86_64-apple-ios-simulator"); 358 ASSERT_FALSE(A.IsExactMatch(B)); 359 // FIXME: See above, though the extra environment complicates things. 360 ASSERT_FALSE(A.IsCompatibleMatch(B)); 361 } 362 { 363 ArchSpec A("x86_64"); 364 ArchSpec B("x86_64-apple-macosx10.14"); 365 // FIXME: The exact match also looks unintuitive. 366 ASSERT_TRUE(A.IsExactMatch(B)); 367 ASSERT_TRUE(A.IsCompatibleMatch(B)); 368 } 369 { 370 ArchSpec A("x86_64"); 371 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 372 // FIXME: The exact match also looks unintuitive. 373 ASSERT_TRUE(A.IsExactMatch(B)); 374 ASSERT_TRUE(A.IsCompatibleMatch(B)); 375 } 376 { 377 ArchSpec A("x86_64-apple-ios12.0.0"); 378 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 379 ASSERT_FALSE(A.IsExactMatch(B)); 380 ASSERT_FALSE(A.IsCompatibleMatch(B)); 381 } 382 { 383 ArchSpec A("x86_64-apple-macosx10.14.2"); 384 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 385 ASSERT_FALSE(A.IsExactMatch(B)); 386 ASSERT_TRUE(A.IsCompatibleMatch(B)); 387 } 388 { 389 ArchSpec A("x86_64-apple-macosx10.14.2"); 390 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 391 // ios-macabi wins. 392 A.MergeFrom(B); 393 ASSERT_TRUE(A.IsExactMatch(B)); 394 } 395 { 396 ArchSpec A("x86_64-apple-macosx10.14.2"); 397 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 398 ArchSpec C(B); 399 // ios-macabi wins. 400 B.MergeFrom(A); 401 ASSERT_TRUE(B.IsExactMatch(C)); 402 } 403 } 404 405 TEST(ArchSpecTest, OperatorBool) { 406 EXPECT_FALSE(ArchSpec()); 407 EXPECT_TRUE(ArchSpec("x86_64-pc-linux")); 408 } 409 410 TEST(ArchSpecTest, TripleComponentsWereSpecified) { 411 { 412 ArchSpec A(""); 413 ArchSpec B("-"); 414 ArchSpec C("--"); 415 ArchSpec D("---"); 416 417 ASSERT_FALSE(A.TripleVendorWasSpecified()); 418 ASSERT_FALSE(A.TripleOSWasSpecified()); 419 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 420 421 ASSERT_FALSE(B.TripleVendorWasSpecified()); 422 ASSERT_FALSE(B.TripleOSWasSpecified()); 423 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 424 425 ASSERT_FALSE(C.TripleVendorWasSpecified()); 426 ASSERT_FALSE(C.TripleOSWasSpecified()); 427 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 428 429 ASSERT_FALSE(D.TripleVendorWasSpecified()); 430 ASSERT_FALSE(D.TripleOSWasSpecified()); 431 ASSERT_FALSE(D.TripleEnvironmentWasSpecified()); 432 } 433 { 434 // TODO: llvm::Triple::normalize treats the missing components from these 435 // triples as specified unknown components instead of unspecified 436 // components. We need to either change the behavior in llvm or work around 437 // this in lldb. 438 ArchSpec A("armv7"); 439 ArchSpec B("armv7-"); 440 ArchSpec C("armv7--"); 441 ArchSpec D("armv7---"); 442 443 ASSERT_FALSE(A.TripleVendorWasSpecified()); 444 ASSERT_FALSE(A.TripleOSWasSpecified()); 445 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 446 447 ASSERT_TRUE(B.TripleVendorWasSpecified()); 448 ASSERT_FALSE(B.TripleOSWasSpecified()); 449 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 450 451 ASSERT_TRUE(C.TripleVendorWasSpecified()); 452 ASSERT_TRUE(C.TripleOSWasSpecified()); 453 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 454 455 ASSERT_TRUE(D.TripleVendorWasSpecified()); 456 ASSERT_TRUE(D.TripleOSWasSpecified()); 457 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 458 } 459 { 460 ArchSpec A("x86_64-unknown"); 461 ArchSpec B("powerpc-unknown-linux"); 462 ArchSpec C("i386-pc-windows-msvc"); 463 ArchSpec D("aarch64-unknown-linux-android"); 464 465 ASSERT_TRUE(A.TripleVendorWasSpecified()); 466 ASSERT_FALSE(A.TripleOSWasSpecified()); 467 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 468 469 ASSERT_TRUE(B.TripleVendorWasSpecified()); 470 ASSERT_TRUE(B.TripleOSWasSpecified()); 471 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 472 473 ASSERT_TRUE(C.TripleVendorWasSpecified()); 474 ASSERT_TRUE(C.TripleOSWasSpecified()); 475 ASSERT_TRUE(C.TripleEnvironmentWasSpecified()); 476 477 ASSERT_TRUE(D.TripleVendorWasSpecified()); 478 ASSERT_TRUE(D.TripleOSWasSpecified()); 479 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 480 } 481 } 482