<!--

/*
** Copyright (c) 2012 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/

-->

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>

<script>
"use strict";
description("Test of getActiveAttrib and getActiveUniform");

var wtu = WebGLTestUtils;
var context = wtu.create3DContext();
var context2 = wtu.create3DContext();
var program = wtu.loadStandardProgram(context);
var program2 = wtu.loadProgramFromFile(context2,
                           "../resources/intArrayUniformShader.vert",
                           "../resources/noopUniformShader.frag");

glErrorShouldBe(context, context.NO_ERROR);
shouldBe("context.getActiveUniform(program, 0).name", "'u_modelViewProjMatrix'");
shouldBe("context.getActiveUniform(program, 0).type", "context.FLOAT_MAT4");
shouldBe("context.getActiveUniform(program, 0).size", "1");
shouldBeNull("context.getActiveUniform(program, 1)");
glErrorShouldBe(context, context.INVALID_VALUE);
shouldBeNull("context.getActiveUniform(program, -1)");
glErrorShouldBe(context, context.INVALID_VALUE);
shouldBeNull("context.getActiveUniform(null, 0)");
glErrorShouldBe(context, context.INVALID_VALUE);

// we don't know the order the attribs will appear.
var info = [
  context.getActiveAttrib(program, 0),
  context.getActiveAttrib(program, 1)
];
for (var ii = 0; ii < info.length; ++ii)
    shouldBeNonNull("info[ii]");

var expected = [
  { name: 'a_normal', type: context.FLOAT_VEC3, size: 1 },
  { name: 'a_vertex', type: context.FLOAT_VEC4, size: 1 }
];

if (info[0].name != expected[0].name) {
  var t = info[0];
  info[0] = info[1];
  info[1] = t;
}

for (var ii = 0; ii < info.length; ++ii) {
  shouldBe("info[ii].name", "expected[ii].name");
  shouldBe("info[ii].type", "expected[ii].type");
  shouldBe("info[ii].size", "expected[ii].size");
}

// we don't know the order the uniforms will appear.
var info2 = [
    context2.getActiveUniform(program2, 0),
    context2.getActiveUniform(program2, 1)
];
for (var ii = 0; ii < info2.length; ++ii)
    shouldBeNonNull("info2[ii]");

var expected2 = [
    { name: 'ival', type: context2.INT, size: 1 },
    { name: 'ival2[0]', type: context2.INT, size: 2 }
];

if (info2[0].name != expected2[0].name) {
    t = info2[0];
    info2[0] = info2[1];
    info2[1] = t;
}

for (var ii = 0; ii < info2.length; ++ii) {
    shouldBe("info2[ii].name", "expected2[ii].name");
    shouldBe("info2[ii].type", "expected2[ii].type");
    shouldBe("info2[ii].size", "expected2[ii].size");
}

shouldBeNull("context.getActiveAttrib(program, 2)");
glErrorShouldBe(context, context.INVALID_VALUE);
shouldBeNull("context.getActiveAttrib(program, -1)");
glErrorShouldBe(context, context.INVALID_VALUE);
shouldBeNull("context.getActiveAttrib(null, 0)");
glErrorShouldBe(context, context.INVALID_VALUE);

glErrorShouldBe(context2, context.NO_ERROR);

debug("Check trying to get attribs from different context");
shouldBeNull("context2.getActiveAttrib(program, 0)");
glErrorShouldBe(context2, context2.INVALID_OPERATION);
shouldBeNull("context2.getActiveUniform(program, 0)");
glErrorShouldBe(context2, context2.INVALID_OPERATION);

debug("Check trying to get attribs from deleted program");
context.deleteProgram(program);
shouldBeNull("context.getActiveUniform(program, 0)");
glErrorShouldBe(context, context.INVALID_VALUE);
shouldBeNull("context.getActiveAttrib(program, 0)");
glErrorShouldBe(context, context.INVALID_VALUE);

var successfullyParsed = true;
</script>

<script src="../../resources/js-test-post.js"></script>
</body>
</html>
