// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "vm/coverage.h" #include "vm/dart_api_impl.h" #include "vm/unit_test.h" namespace dart { #ifndef PRODUCT static RawObject* ExecuteScript(const char* script) { TransitionVMToNative transition(Thread::Current()); Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL); EXPECT_VALID(h_lib); Library& lib = Library::Handle(); lib ^= Api::UnwrapHandle(h_lib); EXPECT(!lib.IsNull()); Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL); EXPECT_VALID(result); return Api::UnwrapHandle(h_lib); } class FunctionCoverageFilter : public CoverageFilter { public: explicit FunctionCoverageFilter(const Function& func) : func_(func) {} bool ShouldOutputCoverageFor(const Library& lib, const Script& script, const Class& cls, const Function& func) const { return func.raw() == func_.raw(); } private: const Function& func_; }; VM_TEST_CASE(Coverage_Empty) { const char* kScript = "main() {\n" "}"; Library& lib = Library::Handle(); lib ^= ExecuteScript(kScript); ASSERT(!lib.IsNull()); JSONStream js; CodeCoverage::PrintJSON(thread, &js, NULL, false); char buf[1024]; OS::SNPrint(buf, sizeof(buf), "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\"," "\"fixedId\":true,\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\"," "\"uri\":\"test-lib\"," "\"_kind\":\"script\"},\"hits\":[]}", lib.index()); EXPECT_SUBSTRING(buf, js.ToCString()); } VM_TEST_CASE(Coverage_MainWithClass) { const char* kScript = "class Foo {\n" " var x;\n" " Foo(this.x);\n" " bar() {\n" " x = x * x;\n" " x = x / 13;\n" " }\n" "}\n" "main() {\n" " var foo = new Foo(7);\n" " foo.bar();\n" "}\n"; Library& lib = Library::Handle(); lib ^= ExecuteScript(kScript); ASSERT(!lib.IsNull()); JSONStream js; CodeCoverage::PrintJSON(thread, &js, NULL, false); char buf[1024]; // Coverage data is printed per class, i.e., there should be two sections // for test-lib in the JSON data. // Data for the actual class Foo. OS::SNPrint(buf, sizeof(buf), "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\"," "\"fixedId\":true,\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\"," "\"uri\":\"test-lib\"," "\"_kind\":\"script\"},\"hits\":[3,1,5,4,6,3]}", lib.index()); EXPECT_SUBSTRING(buf, js.ToCString()); // Data for the fake class containing main(). OS::SNPrint(buf, sizeof(buf), "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\"," "\"fixedId\":true,\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\"," "\"uri\":\"test-lib\"," "\"_kind\":\"script\"},\"hits\":[10,1,11,1]}", lib.index()); EXPECT_SUBSTRING(buf, js.ToCString()); } VM_TEST_CASE(Coverage_FilterFunction) { const char* kScript = "class Foo {\n" " var x;\n" " var y;\n" " Foo(this.x);\n" " Foo.other(this.x, this.y);\n" " Foo.yetAnother();\n" "}\n" "main() {\n" " var foo = new Foo(7);\n" "}\n"; Library& lib = Library::Handle(); lib ^= ExecuteScript(kScript); ASSERT(!lib.IsNull()); const Class& cls = Class::Handle( lib.LookupClass(String::Handle(String::New("Foo")))); ASSERT(!cls.IsNull()); const Function& func = Function::Handle( cls.LookupFunction(String::Handle(String::New("Foo.yetAnother")))); ASSERT(!func.IsNull()); JSONStream js; FunctionCoverageFilter filter(func); CodeCoverage::PrintJSON(thread, &js, &filter, false); // Only expect coverage data for Foo.yetAnother() on line 6. char buf[1024]; OS::SNPrint(buf, sizeof(buf), "{\"source\":\"test-lib\",\"script\":{\"type\":\"@Script\"," "\"fixedId\":true,\"id\":\"libraries\\/%" Pd "\\/scripts\\/test-lib\"," "\"uri\":\"test-lib\"," "\"_kind\":\"script\"},\"hits\":[6,0]}", lib.index()); EXPECT_SUBSTRING(buf, js.ToCString()); } #endif // !PRODUCT } // namespace dart